
#include "UnionMgr.h"
#include "Cache/OfflineCharacterDataMgr.h"
#include "Active/ActiveCharacterMgr.h"
#include "CenterService.h"
#include "Common/Utility/ServerTime.h"
#include "Common/TableDataEx/UnionCfg.h"
#include "Common/GlobalDefine.h"
#include "Duplicate/CenterDuplicateMgr.h"
#include "Common/TableDataEx/DuplicateCfg.h"
#include "Common/TableData/DuplicateDuplicateCfg.h"
#include "SceneMgr/CenterSceneMrg.h"
#include "AccountMgr/CenterAccountMgr.h"
#include "RankingList/RankingListMgr.h"
#include "ActivityMgr/ActivityMgr.h"
#include "EscortMgr/EscortMgr.h"
#include "Script/ScriptMgr_CS.h"
#include "Common/TableData/BoxDropCfg.h"
#include "ActivityMgr/Activity.h"
#include "MallCenter/MallManager.h"
#include "ChatCenter/ChatCenter.h"
#include "Common/TableData/ConstantConstantCfg.h"
#include "Common/TableData/GuildGuildwarCfg.h"
#include "Common/TableData/GuildSupplyCfg.h"
#include "Common/TableData/GuildConstantCfg.h"
#include "Notify/CNotifyMgr.h"

UnionMgr::UnionMgr() :m_pUnionPool(nullptr), m_pUnionCharPool(nullptr)
{
	m_mapUnion.clear();
	m_mapUnionByName.clear();
	m_maxUnionUid = 0;
	m_mapUnionChar.clear();
	m_startLoad = 0;
	m_finishLoad = false;
	m_mapCharUnionID.clear();
	m_vecUnionId.clear();
	m_setCharOfflineSave.clear();
	m_vecUnionRank.clear();
	m_vecCharRank.clear();
	mLostCity[ECamp_Type_Light].Clear();
	mLostCity[ECamp_Type_Dark].Clear();
	m_reCreateUnionScene.clear();
}

UnionMgr::~UnionMgr()
{

}

bool UnionMgr::Init()
{
	m_pUnionPool = new ObjectPool<CUnion>(10, false);
	MMO_ASSERT(nullptr != m_pUnionPool);

	m_pUnionCharPool = new ObjectPool<UnionChar>(10, false);
	MMO_ASSERT(nullptr != m_pUnionCharPool);

	mLostCity[ECamp_Type_Light] = LostCityUnionInfo();
	mLostCity[ECamp_Type_Dark] = LostCityUnionInfo();
	//
	IMessageDispatch *pDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr == pDispatch)
	{
		return false;
	}

	pDispatch->registerDBProxyHandler(EMODULE_ID_UNION, this);

	g_GetActiveCharacterMgr()->AddCharacterObserver(this);

	g_GetTimerAxis()->SetTimer(ETimer_ID_Load_UnionData, 2 * 1000, this);
	//
	g_GetTimerAxis()->SetTimer(ETimer_ID_Save_Char, 60 * 1000, this);
	//
	g_GetTimerAxis()->SetTimer(ETimer_ID_Save_Union, 60 * 1000, this);

	return true;
}

void UnionMgr::SaveAll()
{
	SaveAllCharData();
	SaveAllUnionData();
	SaveLostCityData();
}

void UnionMgr::UnInit()
{
	g_GetActiveCharacterMgr()->RemoveCharacterObserver(this);

	g_GetTimerAxis()->KillAllTimer(this);
	g_GetTimerAxis()->KillAllFixTimer(this);

	//销毁前保存一次
	SaveAllCharData();
	SaveAllUnionData();
	SaveLostCityData();

	IMessageDispatch *pDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr != pDispatch)
	{
		pDispatch->unregisterDBProxyHandler(EMODULE_ID_UNION);
	}

	UnionMap::iterator iter = m_mapUnion.begin();
	for (; iter != m_mapUnion.end(); ++iter)
	{
		CUnion *pUnion = iter->second;
		if (nullptr != pUnion)
		{
			pUnion->UnInit();
			FreeUnion(pUnion);
		}
	}
	UnionCharMap::iterator iterChar = m_mapUnionChar.begin();
	for (; iterChar != m_mapUnionChar.end(); ++iterChar)
	{
		UnionChar *pChar = iterChar->second;
		if (nullptr != pChar)
		{
			pChar->UnInit();
			FreeUnionChar(pChar);
		}
	}

	m_mapUnion.clear();
	m_mapUnionByName.clear();
	m_maxUnionUid = 0;
	m_mapUnionChar.clear();
	m_vecUnionId.clear();
	m_startLoad = 0;
	m_finishLoad = false;
	m_mapCharUnionID.clear();
	m_mapCharApply.clear();
	m_setCharOfflineSave.clear();
	m_vecUnionRank.clear();
	m_vecCharRank.clear();
	m_reCreateUnionScene.clear();

	MMO_DELETE(m_pUnionPool);
	MMO_DELETE(m_pUnionCharPool);
}


//角色登陆
void UnionMgr::onCharacterLogin(ActiveCharacter *pOnlineCharacter)
{
	_UNUSE(pOnlineCharacter);
	//请求DB数据
	CharIDType charId = pOnlineCharacter->GetCharID();
	CharUnionDBRequest req;
	req.set_charid(charId);
	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_CHAR_UNION_DATA_REQ, &req))
	{
		LogErrFmtPrint("[center] UnionMgr::onCharacterLogin...SendDataToDBProxy failed....charid:%llu ", charId);
	}
	SyncUnionLogin(charId);
	//登录的时候逻辑服会同步一次战力，这里在计算一次工会战力
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr != pUnion)
	{
		pUnion->MemFightUpdate(charId);
		//登录的时候，如果申请列表不为空，也需要通知给前端
		if (!pUnion->IsApplyEmpty())
		{
			const SET_INT8 &setApplyDuty = g_GetUnionCfgMgr()->GetApplyLstDuty();
			SET_INT8::const_iterator iterDuty = setApplyDuty.find(pUnion->MemberDuty(charId));
			if (iterDuty != setApplyDuty.end())
			{
				NotifyApplyLstUpdate(pUnion->UnionId(),charId);
			}
		}

		//登录的时候通知一次外观
		if (pUnion->IsMemberDuty(charId, EUnionDutyType_Leader))
		{
			//如果是会长，需要更新工会NPC 外观
			NotifyLeaderFacadeUpdate(pUnion->UnionId());
		}
	}
}
//角色登出
void UnionMgr::onCharacterLogout(ActiveCharacter *pOnlineCharacter)
{
	_UNUSE(pOnlineCharacter);

	CharIDType charId = pOnlineCharacter->GetCharID();
	UnionChar *pChar = CharUnionData(charId);
	if (nullptr != pChar)
	{
		pChar->Save();
		RecycleUnionChar(pChar);
	}
}
//角色更新
void UnionMgr::onCharacterUpdate(ActiveCharacter *pOnlineCharacter)
{
	_UNUSE(pOnlineCharacter);
	//玩家战力改变
	int32_t charFight = pOnlineCharacter->GetLastAttrUpdate(C_FIGHT_POWER);
	if (charFight > 0)
	{
		CharIDType charId = pOnlineCharacter->GetCharID();
		CUnion *pUnion = GetCharUnion(charId);
		if (nullptr != pUnion)
		{
			pUnion->MemFightUpdate(charId);
		}
	}
	
}
//外观改变
void UnionMgr::onCharacterFacadeUpdate(OfflineCharacterData *pOffLineCharacter)
{
	CharIDType charId = pOffLineCharacter->GetCharID();
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr != pUnion)
	{
		if (pUnion->IsMemberDuty(charId,EUnionDutyType_Leader))
		{
			//如果是会长，需要更新工会NPC 外观
			NotifyLeaderFacadeUpdate(pUnion->UnionId());
		}
	}
}
//删除角色
void UnionMgr::onCharacterDel(OfflineCharacterData *pOffLineCharacter)
{
	/*
	a)玩家在公会中删除角色时需要根据玩家的职位做如下处理
	i.玩家不是公会会长，系统强制玩家退出公会
	ii.玩家是公会会长，且公会人数等于1，系统强制解散公会
	iii.玩家是公会会长，且公会人数大于1，做如下判断
	1.如果公会中有多个副会长，则将职位转给历史贡献最高的副会长
	2.如果公会中没有副会长，则将职位转给长老
	a)如果公会中有多个长老，则将职位转给历史贡献最高的长老
	b)如果公会中没有长老，则将职位转给精英
	i.如果公会中有多个精英，则将职位转给历史贡献最高的精英
	ii.如果公会中没有精英，则将职位转给成员
	1.如果公会中有多个成员，则将职位转给历史贡献最高的成员
	*/

	CharIDType charId = pOffLineCharacter->GetCharID();
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr != pUnion)
	{
		if (pUnion->IsMemberDuty(charId,EUnionDutyType_Leader)) //会长
		{
			if (pUnion->MemberCount() <= 1)
			{
				//解散
				Dismiss(charId);
			}
			else
			{
				//副会长
				SET_UINT64 setMem;
				setMem.clear();
				pUnion->DutyMember(setMem, EUnionDutyType_Vice);
				if (setMem.size() <= 0)
				{
					//长老
					pUnion->DutyMember(setMem, EUnionDutyType_Elder);
					if (setMem.size() <= 0)
					{
						//精英
						pUnion->DutyMember(setMem, EUnionDutyType_Elite);
						if (setMem.size() <= 0)
						{
							//普通成员
							pUnion->DutyMember(setMem, EUnionDutyType_Common);
						}
					}
				}
				//历史贡献最高的
				CharIDType dstCid = 0;
				uint32_t historyContri = 0;
				SET_UINT64::iterator iterMem = setMem.begin();
				for (; iterMem != setMem.end(); ++iterMem)
				{
					CharIDType memCid = (*iterMem);
					OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(memCid);
					if (nullptr != pOffline)
					{
						if (historyContri <= 0)
						{
							historyContri = pOffline->GetHistoryContri();
							dstCid = memCid;
						}
						else if (historyContri < pOffline->GetHistoryContri())
						{
							historyContri = pOffline->GetHistoryContri();
							dstCid = memCid;
						}
					}
				}
				//如果找不到，证明出错了，直接解散工会
				OfflineCharacterData *pDstOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(dstCid);
				if (dstCid <= 0 || dstCid == charId || nullptr == pDstOffline)
				{
					LogErrFmtPrint("UnionMgr::onCharacterDel...dstCid <= 0 || dstCid == charId || nullptr == pDstOffline....cid:%lu,dstcid:%lu,historyContri:%u ", charId, dstCid, historyContri);
					//出错了，直接解散工会
					Dismiss(charId);
				}
				else
				{
					//这里实际流程是 会长先转让，会长变成成员，然后再退出工会
					CUnion *pTransUnion = Trans(charId, dstCid);
					if (nullptr != pTransUnion)
					{
						OnQuit(charId, pTransUnion, true);
						DelCharOfflineSave(charId);
					}
					else
					{
						//失败，直接解散工会
						LogErrFmtPrint("UnionMgr::onCharacterDel...Trans failed....cid:%lu,dstcid:%lu,historyContri:%u ", charId, dstCid, historyContri);
						//出错了，直接解散工会
						Dismiss(charId);
					}
				}
			}			
			
		}
		else
		{
			//离开
			QuitUnion(charId);
			//
			DelCharOfflineSave(charId);
		}
	}
	//这里需要删除玩家之前申请过的所有工会
	ClearCharApply(charId);
	//删除DB
	DelCharUnionData(charId);
}
//切换场景
void UnionMgr::onCharacterSwitchScene(ActiveCharacter *pOnlineCharacter)
{
	_UNUSE(pOnlineCharacter);
}
//断开连接
void UnionMgr::onCharacterDisconnect(ActiveCharacter *pOnlineCharacter)
{
	_UNUSE(pOnlineCharacter);
}

void UnionMgr::onDBProxyMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	_UNUSE(package);
	switch (actionId)
	{
	case DBPROXY_PROTOCOL_ALL_UNION_DATA_RSP:
		{
			UnionDBResponse rsp;
			if (rsp.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
			{
				LoadAllUnionDataDBRet(rsp);
			}
			else
			{
				LogErrFmtPrint("[center] UnionMgr::onDBProxyMessage.....UnionDBResponse parse failed....");
			}			
		}
		break;
	case DBPROXY_PROTOCOL_ALL_CHAR_UNION_OFFLINE_RSP:
		{
			CharUnionDBOfflineResponse rsp;
			if (rsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
			{
				LoadAllCharUnionOfflineDataDBRet(rsp);
			}
			else
			{
				LogErrFmtPrint("[center] UnionMgr::onDBProxyMessage.....UnionDBResponse parse failed....");
			}
		}
		break;
	case DBPROXY_PROTOCOL_CHAR_UNION_DATA_RSP:
		{
			CharUnionDBReponse rsp;
			if (rsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
			{
				LoadCharUnionDataDBRet(rsp);
			}
			else
			{
				LogErrFmtPrint("[center] UnionMgr::onDBProxyMessage.....CharUnionDBReponse parse failed....");
			}
		}
		break;
	default:
		break;
	}
}

void UnionMgr::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
}

void UnionMgr::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case ETimer_ID_Load_UnionData:
		{
			if (g_GetCenterService()->IsConnectDBProxy() && g_GetOfflineCharacterDataMgr()->IsFinishLoad())
			{
				//开始加载离线工会数据
				int32_t offset = 0;
				m_startLoad = g_GetGlobalServerTime()->UnixSec();			
				
				UnionDBRequest req;
				req.set_offset(offset);
				if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_ALL_UNION_DATA_REQ, &req))
				{
					MMOLOG_FMT_ERROR("[center] load all union data.... SendDataToDBProxy failed...offset:%d ", offset);
				}
				else
				{
					LogDebugFmtPrint("[center] start load all unioin data....");
				}

				GlobalDBRequst lostCityDataReq;
				lostCityDataReq.set_type_id(EGlobalType_LostCity);
				if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_GLOBAL_GET_REQ, &lostCityDataReq))
				{
					MMOLOG_FMT_ERROR("[center] load lostCityData.... SendDataToDBProxy failed...offset:%d ", offset);
				}

				g_GetTimerAxis()->KillTimer(ETimer_ID_Load_UnionData, this);

			}
		}
		break;
	case ETimer_ID_Save_Char:
		{
			if (g_GetCenterService()->IsConnectDBProxy() && m_finishLoad)
			{
				SaveAllCharData();
			}
		}
		break;
	case ETimer_ID_Save_Union:
		{
			if (g_GetCenterService()->IsConnectDBProxy() && m_finishLoad)
			{
				SaveAllUnionData();
			}
		}
		break;
	case ETimer_ID_Create_UnionHome_Scene:
		{
			if (m_finishLoad)  //加载完成之后才开始 创建工会驻地场景
			{
				//需要判断工会驻地地图所在的逻辑服是否已经和中心服建立连接
				uint32_t unionHomeDup = g_GetDuplicateCfgMgr()->GetUnionHomeDupId();
				const DuplicateDuplicateCfgInfo *pDupCfg = g_GetDuplicateDuplicateCfgTable()->GetDuplicateDuplicateCfgInfo(unionHomeDup);
				if (nullptr != pDupCfg)
				{
					uint32_t logicId = g_GetCenterSceneMgr()->GetLogicIdByMapId(pDupCfg->sceneResource);
					if (nullptr != g_GetCenterService()->GetLogicSession(logicId))
					{
						CreateAllUnionScene();
						//移除定时器
						g_GetTimerAxis()->KillTimer(ETimer_ID_Create_UnionHome_Scene, this);
					}
				}
			}			
		}
		break;
	case ETimer_ID_ReCreate_UnionHome_Scene:
		{
			if (m_finishLoad)  //加载完成之后才开始 创建工会驻地场景
			{
				//需要判断工会驻地地图所在的逻辑服是否已经和中心服建立连接
				uint32_t unionHomeDup = g_GetDuplicateCfgMgr()->GetUnionHomeDupId();
				const DuplicateDuplicateCfgInfo *pDupCfg = g_GetDuplicateDuplicateCfgTable()->GetDuplicateDuplicateCfgInfo(unionHomeDup);
				if (nullptr != pDupCfg)
				{
					uint32_t logicId = g_GetCenterSceneMgr()->GetLogicIdByMapId(pDupCfg->sceneResource);
					if (nullptr != g_GetCenterService()->GetLogicSession(logicId))
					{
						//连接上逻辑服之后重新创建 原来在该 逻辑服的 工会驻地场景
						ReCreateUnionScene();
						//移除定时器
						g_GetTimerAxis()->KillTimer(ETimer_ID_ReCreate_UnionHome_Scene, this);
					}
				}
				else
				{
					LogErrFmtPrint("[center] UnionMgr::OnTimer...recreate union home scene..nullptr == pDupCfg...dupid:%u ", unionHomeDup);
				}
			}
		}
		break;
	default:
		break;
	}
}

void UnionMgr::SaveAllUnionData()
{
	UnionMap::iterator iter = m_mapUnion.begin();
	for (; iter != m_mapUnion.end(); ++iter)
	{
		CUnion *pUnion = iter->second;
		if (nullptr != pUnion)
		{
			pUnion->Save();
		}
	}
}

void UnionMgr::SaveAllCharData()
{
	UnionCharMap::iterator iter = m_mapUnionChar.begin();
	for (; iter != m_mapUnionChar.end(); ++iter)
	{
		UnionChar *pChar = iter->second;
		if (nullptr != pChar)
		{
			pChar->Save();
		}
	}

	//
	SET_UINT64::iterator iterOffline = m_setCharOfflineSave.begin();
	while (iterOffline != m_setCharOfflineSave.end())
	{
		CharIDType charId = (*iterOffline);
		SaveCharOfflineData(charId);
		++iterOffline;
	}
	m_setCharOfflineSave.clear();
}

void UnionMgr::SaveCharOfflineData(CharIDType charId)
{
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr != pOffline)
	{

		SaveCharUnionDBRequest req;
		req.set_charid(charId);
		req.set_type(ECharUnionDataType_Offline);

		CharUnionDBOfflineData protoOffline;
		protoOffline.set_use_contri(pOffline->GetUnionUseContri());
		protoOffline.set_history_contri(pOffline->GetHistoryContri());
		protoOffline.set_lost_city_val(pOffline->GetLostCityVal());
		string strData = protoOffline.SerializeAsString();
		//设置数据
		req.set_data(strData);
		if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_SAVE_CHAR_UNION_DATA_REQ, &req))
		{
			LogErrFmtPrint("[center] UnionMgr::SaveCharOfflineData....SendDataToDBProxy failed...charID:%llu ", charId);
		}
	}
}

void UnionMgr::LoadLostCityData(const string &data)
{
	if (data.length() <= 0)
	{
		return;
	}
	LostCityDBData lostCity;
	if (!lostCity.ParseFromArray(data.c_str(), (int32_t)data.length()))
	{
		MMOLOG_FMT_ERROR("[center] LoadLostCityData LostCityDBData parase failed...");
		return;
	}
	size_t len = 0;
	const LostCityUnionProto &lightUnion = lostCity.light_union();
	mLostCity[ECamp_Type_Light].unionId = lightUnion.unionid();
	mLostCity[ECamp_Type_Light].score = lightUnion.score();
	len = lightUnion.char_list_size();
	for (size_t i = 0; i != len; ++i)
	{
		const LostCityCharProto &charProto = lightUnion.char_list(i);
		CUnion *pUnion = GetCharUnion(charProto.charid());
		if (nullptr == pUnion)	continue;
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charProto.charid());
		if (nullptr == pOffline)	continue;
		LostCityCharInfo charInfo;
		charInfo.charId = charProto.charid();
		charInfo.charName = pOffline->GetCharName();
		charInfo.charLv = pOffline->GetLevel();
		charInfo.convoyValue = charProto.convoyvalue();
		charInfo.killValue = charProto.killvalue();
		charInfo.totalValue = charInfo.convoyValue + charInfo.killValue;
		mLostCity[ECamp_Type_Light].scoreVec.push_back(charInfo);
	}
	len = lightUnion.title_list_size();
	for (size_t i = 0; i != len; ++i)
	{
		const LostCityTitleProto &titleProto = lightUnion.title_list(i);
		CUnion *pUnion = GetCharUnion(titleProto.charid());
		if (nullptr == pUnion)	continue;
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(titleProto.charid());
		if (nullptr == pOffline)	continue;
		LostCityOfflineTitle offTitle;
		offTitle.titleId = titleProto.title();
		offTitle.startTime = titleProto.starttime();
		mLostCity[ECamp_Type_Light].titleMap[titleProto.charid()] = offTitle;
	}

	const LostCityUnionProto &darkUnion = lostCity.dark_union();
	mLostCity[ECamp_Type_Dark].unionId = darkUnion.unionid();
	mLostCity[ECamp_Type_Dark].score = darkUnion.score();
	len = darkUnion.char_list_size();
	for (size_t i = 0; i != len; ++i)
	{
		const LostCityCharProto &charProto = darkUnion.char_list(i);
		CUnion *pUnion = GetCharUnion(charProto.charid());
		if (nullptr == pUnion)	continue;
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charProto.charid());
		if (nullptr == pOffline)	continue;
		LostCityCharInfo charInfo;
		charInfo.charId = charProto.charid();
		charInfo.charName = pOffline->GetCharName();
		charInfo.charLv = pOffline->GetLevel();
		charInfo.convoyValue = charProto.convoyvalue();
		charInfo.killValue = charProto.killvalue();
		charInfo.totalValue = charInfo.convoyValue + charInfo.killValue;
		mLostCity[ECamp_Type_Dark].scoreVec.push_back(charInfo);
	}
	len = darkUnion.title_list_size();
	for (size_t i = 0; i != len; ++i)
	{
		const LostCityTitleProto &titleProto = darkUnion.title_list(i);
		CUnion *pUnion = GetCharUnion(titleProto.charid());
		if (nullptr == pUnion)	continue;
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(titleProto.charid());
		if (nullptr == pOffline)	continue;
		LostCityOfflineTitle offTitle;
		offTitle.titleId = titleProto.title();
		offTitle.startTime = titleProto.starttime();
		mLostCity[ECamp_Type_Dark].titleMap[titleProto.charid()] = offTitle;
	}
}

void UnionMgr::NotifyLostCityAwards(CharIDType charId, bool isLogin)
{
	ActiveCharacter *pOlineActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOlineActiveCharacter)	return;

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)	return;

	ActivityLostCityAwardsUpdate rsp;
	rsp.set_retcode(RET_SUCCESS);
	uint32_t unionId = GetCharUnionId(charId);
	if (unionId <= 0 || (unionId != mLostCity[ECamp_Type_Light].unionId && unionId != mLostCity[ECamp_Type_Dark].unionId))
	{
		return;
	}
	LostCityUnionInfo &unionInfo = (unionId == mLostCity[ECamp_Type_Light].unionId) ? mLostCity[ECamp_Type_Light] : mLostCity[ECamp_Type_Dark];
	LostCityCharInfo* charInfo = FindCityScore(unionInfo.scoreVec, charId);
	if (nullptr != charInfo)
	{
		rsp.set_score(charInfo->totalValue);
		rsp.set_total_score(pOffline->GetLostCityVal());
		rsp.set_is_get(charInfo->isGet);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
	}

	if (!isLogin)	return;

	//登录: 遗失之城结束时离线角色的称号派发,在这里处理一下
	LOSTCITYTITLE_MAP &titleMap = unionInfo.titleMap;
	LOSTCITYTITLE_MAP::iterator iter = titleMap.find(charId);
	if (iter != titleMap.end())
	{
		LostCityOfflineTitle &offTitle = iter->second;
		uint32_t passTime = Time::Now().sec() - offTitle.startTime;
		if (passTime < ACTIVITY_LOST_CITY_TITLE_EFFECT_TIME)
		{
			CLActivityGetReward notify;
			notify.set_charid(charId);
			notify.set_lefttime(ACTIVITY_LOST_CITY_TITLE_EFFECT_TIME - passTime);
			notify.set_titleid(offTitle.titleId);
			g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_ACTIVITY, CENTER_TO_LOGIC_ACTIVITY_GETREWARD, &notify);
		}
		titleMap.erase(iter);
	}
}

void UnionMgr::LostCityJoinUnion(CharIDType charId)
{
	ActivityLostCityAwardsUpdate notify;
	notify.set_retcode(RET_SUCCESS);
	notify.set_score(0);
	notify.set_total_score(0);
	notify.set_is_get(false);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &notify);
}

uint32_t UnionMgr::GetWinUnionId()
{
	if (mLostCity[ECamp_Type_Light].unionId <= 0 || mLostCity[ECamp_Type_Dark].unionId <= 0)
		return 0;
	if (mLostCity[ECamp_Type_Light].score == 0 && mLostCity[ECamp_Type_Dark].score == 0)	
		return 0;
	if (mLostCity[ECamp_Type_Light].score > mLostCity[ECamp_Type_Dark].score)
		return mLostCity[ECamp_Type_Light].unionId;
	else
		return mLostCity[ECamp_Type_Dark].unionId;
	return 0;
}

void UnionMgr::SaveLostCityData()
{
	if (mLostCity[ECamp_Type_Light].unionId <= 0 || mLostCity[ECamp_Type_Dark].unionId <= 0)
	{
		return;
	}
	GlobalDBSetRequest req;
	req.set_type_id(EGlobalType_LostCity);

	LostCityDBData lostCity;
	LostCityUnionProto *lightUnion = lostCity.mutable_light_union();
	lightUnion->set_unionid(mLostCity[ECamp_Type_Light].unionId);
	lightUnion->set_score(mLostCity[ECamp_Type_Light].score);
	for (LOSTCITYSOCRE_VEC::iterator ib = mLostCity[ECamp_Type_Light].scoreVec.begin(), ie = mLostCity[ECamp_Type_Light].scoreVec.end(); ib != ie; ++ib)
	{
		LostCityCharProto *charProto = lightUnion->add_char_list();
		charProto->set_charid((*ib).charId);
		charProto->set_convoyvalue((*ib).convoyValue);
		charProto->set_killvalue((*ib).killValue);
	}
	for (LOSTCITYTITLE_MAP::iterator ib = mLostCity[ECamp_Type_Light].titleMap.begin(), ie = mLostCity[ECamp_Type_Light].titleMap.end(); ib != ie; ++ib)
	{
		LostCityTitleProto *titleProto = lightUnion->add_title_list();
		titleProto->set_charid(ib->first);
		titleProto->set_title(ib->second.titleId);
		titleProto->set_starttime(ib->second.startTime);
	}
	LostCityUnionProto *darkUnion = lostCity.mutable_dark_union();
	darkUnion->set_unionid(mLostCity[ECamp_Type_Dark].unionId);
	darkUnion->set_score(mLostCity[ECamp_Type_Dark].score);
	for (LOSTCITYSOCRE_VEC::iterator ib = mLostCity[ECamp_Type_Dark].scoreVec.begin(), ie = mLostCity[ECamp_Type_Dark].scoreVec.end(); ib != ie; ++ib)
	{
		LostCityCharProto *charProto = darkUnion->add_char_list();
		charProto->set_charid((*ib).charId);
		charProto->set_convoyvalue((*ib).convoyValue);
		charProto->set_killvalue((*ib).killValue);
	}
	for (LOSTCITYTITLE_MAP::iterator ib = mLostCity[ECamp_Type_Dark].titleMap.begin(), ie = mLostCity[ECamp_Type_Dark].titleMap.end(); ib != ie; ++ib)
	{
		LostCityTitleProto *titleProto = lightUnion->add_title_list();
		titleProto->set_charid(ib->first);
		titleProto->set_title(ib->second.titleId);
		titleProto->set_starttime(ib->second.startTime);
	}
	req.set_data(lostCity.SerializeAsString());
	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_GLOBAL_SAVE_REQ, &req))
	{
		LogErrFmtPrint("[center] UnionMgr::SaveLostCityData.....SendDataToDBProxy faild...");
	}
}

void UnionMgr::DelCharUnionData(CharIDType charId)
{
	DelCharUnionDBRequest req;
	req.set_charid(charId);
	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_DEL_CHAR_UNION_DATA_REQ, &req))
	{
		LogErrFmtPrint("[center] UnionMgr::DelCharUnionData....SendDataToDBProxy failed...charID:%llu ", charId);
	}
}

void UnionMgr::DelUnionDBData(uint32_t unionId)
{
	//DB 删除工会
	DelUnionDBRequest reqDel;
	reqDel.set_union_id(unionId);
	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_DEL_UNION_REQ, &reqDel))
	{
		LogErrFmtPrint("[center] UnionMgr::Dismiss....SendDataToDBProxy failed....unionId:%u ", unionId);
	}
}

void UnionMgr::SetPageListProto(UnionListPageProto *protoUnionPageList, int32_t pageIndex, VEC_UINT32 &vecUnionIds, CharIDType charId /*= 0*/)
{
	if (nullptr == protoUnionPageList || pageIndex < 1)
	{
		return;
	}
	int32_t totalSize = (int32_t)vecUnionIds.size();
	int32_t totalPage = totalSize / UNION_MAX_PAGE_COUNT;
	if ( 0 != (totalSize % UNION_MAX_PAGE_COUNT) )
	{
		totalPage += 1;
	}
	//
	protoUnionPageList->set_page_index(pageIndex);
	protoUnionPageList->set_page_total(totalPage);
	if (totalPage <= 0)
	{
		protoUnionPageList->set_page_total(1);
	}
	UnionListProto *protoUnionList = protoUnionPageList->mutable_lst();
	if (totalSize > 0)
	{
		if (pageIndex <= totalPage)
		{
			int32_t beginIdx = (pageIndex - 1) * UNION_MAX_PAGE_COUNT;
			int32_t endIdx = pageIndex * UNION_MAX_PAGE_COUNT - 1;
			if (endIdx >= totalSize)
			{
				endIdx = totalSize - 1;
			}
			for (int32_t i = beginIdx; i <= endIdx; ++i)
			{
				uint32_t unionId = vecUnionIds.at(i);
				CUnion *pUnion = GetUnion(unionId);
				if (nullptr != pUnion)
				{
					if (nullptr != protoUnionList)
					{
						UnionProto *protoUnion = protoUnionList->add_union_lst();
						if (nullptr != protoUnion)
						{
							pUnion->SetUnionProto(protoUnion, charId);
						}
					}
				}
			}
		}
	}

}

void UnionMgr::UpdateCharUnionInfo(CharIDType charId)
{
	CL_UnionCharUpdateRsp rsp;
	rsp.set_charid(charId);
	string strName = "";
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr != pUnion)
	{
		strName = pUnion->Name();
		rsp.set_union_id(pUnion->UnionId());
		rsp.set_union_duty(pUnion->MemberDuty(charId));
		rsp.set_union_level(pUnion->BuildLev(EUnionBuildType_Hall));
		rsp.set_union_icon(pUnion->IconId());
		rsp.set_office_level(pUnion->BuildLev(EUnionBuildType_Office));
		rsp.set_vault_level(pUnion->BuildLev(EUnionBuildType_Vault));
		rsp.set_union_home_scene(pUnion->UnionSceneId());
	}
	else
	{
		rsp.set_union_id(0);
		rsp.set_union_duty(EUnionDutyType_None);
		rsp.set_union_level(0);
		rsp.set_union_icon(0);
		rsp.set_office_level(0);
		rsp.set_vault_level(0);
		rsp.set_union_home_scene(0);
	}
	rsp.set_union_name(strName);
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr != pOffline)
	{
		rsp.set_union_contri(pOffline->GetUnionUseContri());
		rsp.set_history_contri(pOffline->GetHistoryContri());
	}
	//
	g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_UNION, CENTER_TO_LOGIC_CHAR_UNION_UPDATE, &rsp);
}

void UnionMgr::SyncUnionInfo(CharIDType charId)
{
	Union_SyncInfoRsp rsp;
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr != pUnion)
	{
		rsp.set_union_id(pUnion->UnionId());
		rsp.set_union_name(pUnion->Name());
		rsp.set_union_duty(pUnion->MemberDuty(charId));
		rsp.set_cloud_state((int32_t)pUnion->IsCloudPass());
		rsp.set_union_icon(pUnion->IconId());
	}
	else
	{
		rsp.set_union_id(0);
		rsp.set_union_name("");
		rsp.set_union_duty(EUnionDutyType_None);
		rsp.set_cloud_state(0);
		rsp.set_union_icon(0);
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr != pOffline)
	{
		rsp.set_can_use_contri(pOffline->GetUnionUseContri());
		rsp.set_history_contri(pOffline->GetHistoryContri());
	}

	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_UNION, CENTER_TO_CLIENT_UNION_SYNC_INFO, &rsp);
}

void UnionMgr::SyncUnionLogin(CharIDType charId)				//登录同步工会信息
{
	Union_SyncLoginRsp rsp;
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr != pUnion)
	{
		rsp.set_duty(pUnion->MemberDuty(charId));
		UnionProto *protoUnion = rsp.mutable_info();
		UnionMgrProto* protoMgr = rsp.mutable_mgr();
		pUnion->SetUnionProto(protoUnion);
		pUnion->SetUnionMgrProto(protoMgr);
		rsp.set_fetch(pUnion->IsFetchScore(charId));
		rsp.set_cloud_state((int32_t)pUnion->IsCloudPass());
		rsp.set_union_icon(pUnion->IconId());
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr != pOffline)
	{
		rsp.set_can_use_contri(pOffline->GetUnionUseContri());
		rsp.set_history_contri(pOffline->GetHistoryContri());
	}

	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_UNION, CENTER_TO_CLIENT_UNION_SYNC_LOGIN, &rsp);
}

bool UnionMgr::CreateUnionSceneRes(uint32_t unionId, int8_t sceneType, uint32_t sceneId)//创建工会相关类型场景结果
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr == pUnion)
	{
		LogErrFmtPrint("[center] CreateUnionSceneRes....union not exists....unionid:%u, sceneType:%d, sceneid:%u ", unionId, sceneType, sceneId);
		return false;
	}

	LogInfoFmtPrint("[center] create union  scene success....unionid:%u,sceneType:%d, sceneid:%u ", unionId, sceneType, sceneId);

	pUnion->CreateSceneRes(sceneType,sceneId);

	if (EUnionSceneType_Home == sceneType) //工会驻地场景创建成功
	{
		//通知逻辑服绑定成功
		uint32_t logicId = g_GetCenterDuplicateMgr()->dupSceneLogic(sceneId);
		NotifyLogicBindHome(unionId, sceneId, logicId);
		//通知逻辑服会长外观
		NotifyLeaderFacadeUpdate(unionId);
		//工会驻地场景创建完成之后，需要同步下角色信息到逻辑服
		SET_UINT64 setMem;
		setMem.clear();
		pUnion->AllMember(setMem);
		SET_UINT64::iterator iterMem = setMem.begin();
		for (; iterMem != setMem.end(); ++iterMem)
		{
			CharIDType cid = (*iterMem);
			uint32_t logicId = g_GetCenterAccountMgr()->GetLogicIdByCid(cid);
			if (nullptr != g_GetCenterService()->GetLogicSession(logicId))
			{
				//同步成员信息
				UpdateCharUnionInfo(cid);
			}
		}
		//检查工会活动是否开启
		CheckActForUnionSceneRes(pUnion);
	}

	return true;
}

void UnionMgr::CheckActForUnionSceneRes(CUnion *pUnion) //工会驻地创建成功之后的活动检查
{
	if (nullptr == pUnion)
	{
		return;
	}
	//工会场景创建成功之后，检查活动是否开启
	//如果工会在活动开启之前创建的，需要开启活动，如果在活动期间创建的工会，则不会开启活动
	uint32_t goblinActId = g_GetDuplicateCfgMgr()->GetGoblinActId();
	uint32_t ancientElfActId = g_GetDuplicateCfgMgr()->GetAncientElfActId();

	uint64_t createTime = pUnion->CreateTime();
	uint32_t sceneId = pUnion->UnionSceneId();
	SUnionActParam param;
	pUnion->GetActParam(param);
	param.actScene = sceneId;
	uint32_t logicId = g_GetCenterDuplicateMgr()->dupSceneLogic(sceneId);
	//哥布林
	CActivity *pGoblinAct = g_GetActivityMgr()->GetActivity(goblinActId);
	if (nullptr != pGoblinAct && pGoblinAct->IsRuning())
	{
		if (createTime < pGoblinAct->GetStartTime()) //工会在活动开启之前创建的,通知工会驻地场景
		{
			//NotifyLogicActState(unionId, sceneId, logicId, goblinActId, 1, averageLev);
			NotifyLogicActState(logicId, goblinActId, 1, param);
		}
	}

	//远古精灵
	CActivity *pAncientElfAct = g_GetActivityMgr()->GetActivity(ancientElfActId);
	if (nullptr != pAncientElfAct && pAncientElfAct->IsRuning())
	{
		if (createTime < pAncientElfAct->GetStartTime()) //工会在活动开启之前创建的,通知工会驻地场景
		{
			//NotifyLogicActState(unionId, sceneId, logicId, ancientElfActId, 1, averageLev);
			NotifyLogicActState(logicId, ancientElfActId, 1, param);
		}
	}
}

void UnionMgr::CreateAllUnionScene()
{
	UnionMap::iterator iter = m_mapUnion.begin();
	for (; iter != m_mapUnion.end(); ++iter)
	{
		CreateUnionScene(iter->first,(int32_t)iter->second->Level());
	}
}
bool UnionMgr::CreateUnionScene(uint32_t unionId,int32_t lev)
{
	if (RET_SUCCESS != g_GetCenterDuplicateMgr()->createUnionHomeDup(unionId,lev))
	{
		LogErrFmtPrint("[center] UnionMgr::CreateUnionScene failed.....unionId:%u ", unionId);
		return false;
	}
	return true;
}

void UnionMgr::ReCreateUnionScene()//断线重连之后重新创建工会驻地场景
{
	SET_UINT32::iterator iter = m_reCreateUnionScene.begin();
	for (; iter != m_reCreateUnionScene.end(); ++iter)
	{
		uint32_t unionId = (*iter);
		CUnion *pUnion = GetUnion(unionId);
		if (nullptr != pUnion)
		{
			uint32_t unionSceneId = pUnion->UnionSceneId();
			if (nullptr == g_GetCenterDuplicateMgr()->getDuplicate(unionSceneId))
			{
				CreateUnionScene(pUnion->UnionId(), (int32_t)pUnion->Level());
			}
		}
	}
	m_reCreateUnionScene.clear();
}

void UnionMgr::WeekUpdate()	//任务每周零点更
{
	UnionCharMap::iterator iter = m_mapUnionChar.begin();
	for (; iter != m_mapUnionChar.end(); ++iter)
	{
		UnionChar *pChar = iter->second;
		if (nullptr != pChar)
		{
			pChar->WeekUpdate();
		}
	}
	UnionMap::iterator iterUnion = m_mapUnion.begin();
	for (; iterUnion != m_mapUnion.end(); ++iterUnion)
	{
		CUnion *pUnion = iterUnion->second;
		if (nullptr != pUnion)
		{
			pUnion->WeekUpdate();
		}
	}
}

void UnionMgr::DailyUpdate()  //每日零点更新
{
	UnionCharMap::iterator iter = m_mapUnionChar.begin();
	for (; iter != m_mapUnionChar.end(); ++iter)
	{
		UnionChar *pChar = iter->second;
		if (nullptr != pChar)
		{
			pChar->DayUpdate();
		}
	}
}

bool UnionMgr::AddUnionMoney(CharIDType charId, int32_t money)	//增加工会资金
{
	_UNUSE(charId);
	_UNUSE(money);

	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return false;
	}
	pUnion->AddUnionMoney(money);

	return true;
}

bool UnionMgr::AddCharCanUseContri(CharIDType charId, int32_t contri, ItemOrCurrencySource source)	//增加玩家可用贡献
{
	_UNUSE(charId);
	_UNUSE(contri);
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		return false;
	}
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return false;
	}
	int32_t useContri = (int32_t)pOffline->GetUnionUseContri() + contri;
	useContri = (useContri < 0) ? 0 : useContri;
	pOffline->SetUnionUseContri((uint32_t)useContri);
	//每周和历史贡献只计算累加，不计算消耗的
	if (contri > 0)
	{
		int32_t historyContri = (int32_t)pOffline->GetHistoryContri() + contri;
		historyContri = (historyContri < 0) ? 0 : historyContri;
		pOffline->SetHistoryContri((uint32_t)historyContri);
	
		//
		pUnion->AddCharUseContri(charId, contri);
	}

	LogCurrencyContri(pOffline, contri, source);

	//保存
	AddCharOfflineSave(charId);

	//同步
	SyncUnionInfo(charId);

	//通知逻辑服
	UpdateCharUnionInfo(charId);

	//这里需要通知排行那边 历史共献改变
	RankingListClanContribute useContriChange;
	useContriChange.set_clanname(pUnion->Name());
	useContriChange.set_contributevalue(pOffline->GetHistoryContri());
	useContriChange.set_username(pOffline->GetCharName());
	useContriChange.set_camp(pUnion->CampId());
	g_GetRankingListMgr()->ChangeClanContribute(useContriChange);


	return true;

}

//清空公会所有玩家的所有公会贡献
bool UnionMgr::ClearAllCharAllContri()
{
	//获取所有公会
	UnionMap::iterator iter= m_mapUnion.begin();
	for (; iter != m_mapUnion.end();++iter)
	{
		CUnion* pUnion = iter->second;
		if (pUnion)
		{
			const UnionMemberMap * pMember = pUnion->GetUnionAllMember();
			if (pMember)
			{
				UnionMemberMap::const_iterator iterMember = pMember->begin();
				for (; iterMember != pMember->end();++iterMember)
				{
					AddCharCanUseContri(iterMember->first,-1000000, S_UNION);
					AddCharHistoryContri(iterMember->first, -1000000);
					pUnion->SetCharWeekContri((UnionMember &)iterMember->second, 0, Time::Now().UnixSec());
				}
			}
		}
	}

	return true;
}



bool UnionMgr::AddCharHistoryContri(CharIDType charId, int32_t historyContri) //增加历史贡献
{
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		return false;
	}
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return false;
	}
	int32_t history = (int32_t)pOffline->GetHistoryContri() + historyContri;
	history = (history < 0) ? 0 : history;
	pOffline->SetHistoryContri((uint32_t)history);
	UpdateCharUnionInfo(charId);
	//
	SyncUnionInfo(charId);

	//保存
	AddCharOfflineSave(charId);


	//这里需要通知排行那边 历史共献改变
	RankingListClanContribute useContriChange;
	useContriChange.set_clanname(pUnion->Name());
	useContriChange.set_contributevalue(pOffline->GetHistoryContri());
	useContriChange.set_username(pOffline->GetCharName());
	useContriChange.set_camp(pUnion->CampId());
	g_GetRankingListMgr()->ChangeClanContribute(useContriChange);

	return true;
}

bool UnionMgr::AddUnionResearchLev(CharIDType charId, int8_t researchType, int8_t addLev) //增加工会研究等级
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return false;
	}
	if (!ValidResearchType(researchType))
	{
		return false;
	}
	if (addLev <= 0)
	{
		return false;
	}
	if (!pUnion->AddResearchLev(researchType,addLev))
	{
		return false;
	}
	//增加等级成功，这里通知前端
	UnionResearchInfoRsp rsp;
	rsp.set_retcode(RET_SUCCESS);
	UnionAllResearchProto *proto = rsp.mutable_info();
	pUnion->SetUnionResearchProto(proto);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_UNION, CENTER_TO_CLIENT_UNION_RESEARCH_INFO, &rsp);

	return true;
}


int32_t UnionMgr::GetCharScoreRank(CharIDType charId) //获取玩家积分排名
{
	int32_t isize = m_vecCharRank.size();
	for (int32_t i = 0; i < isize; ++i)
	{
		if (charId == m_vecCharRank[i].rankId)
		{
			return i + 1;
		}
	}
	return 0;
}

int32_t UnionMgr::GetUnionScoreRank(uint32_t unionId)//获取工会积分排名
{
	int32_t isize = m_vecUnionRank.size();
	for (int32_t i = 0; i < isize; ++i)
	{
		if (unionId == m_vecUnionRank[i].rankId)
		{
			return i + 1;
		}
	}
	return 0;
}

void UnionMgr::OnUnionSceneClose(MAP_UINT32_SET_INT32 &mapUnionScene) //工会场景关闭
{
	//工会相关的场景关闭了,清空工会相关的场景
	MAP_UINT32_SET_INT32::iterator iterUnion = mapUnionScene.begin();
	for (; iterUnion != mapUnionScene.end(); ++iterUnion)
	{
		CUnion *pUnion = GetUnion(iterUnion->first);
		if (nullptr != pUnion)
		{
			SET_INT32 &setSceneType = iterUnion->second;
			SET_INT32::iterator iterType = setSceneType.begin();
			for (; iterType != setSceneType.end(); ++iterType)
			{
				int8_t sceneType = (*iterType);
				pUnion->CreateSceneRes(sceneType, 0); //工会相关的场景ID清零
				if (EUnionSceneType_Home == sceneType) //工会驻地
				{
					m_reCreateUnionScene.insert(pUnion->UnionId());
				}
			}
		}
	}
	
}

LostCityCharInfo* UnionMgr::FindCityScore(CharIDType charId)	//角色积分信息
{
	uint32_t unionId = GetCharUnionId(charId);
	if (unionId <= 0)
	{
		return nullptr;
	}
	if (unionId != mLostCity[ECamp_Type_Light].unionId && unionId != mLostCity[ECamp_Type_Dark].unionId)
	{
		return nullptr;
	}
	LostCityUnionInfo &unionInfo = (unionId == mLostCity[ECamp_Type_Light].unionId) ? mLostCity[ECamp_Type_Light] : mLostCity[ECamp_Type_Dark];
	LostCityCharInfo* charInfo = FindCityScore(unionInfo.scoreVec, charId);
	return charInfo;
}

LostCityCharInfo* UnionMgr::FindCityScore(LOSTCITYSOCRE_VEC &vec, CharIDType charId)	//角色积分信息
{
	/*LostCityCharInfo *charInfo = nullptr;
	for (LOSTCITYSOCRE_VEC::iterator iter = vec.begin(); iter != vec.end(); ++iter)
	{
		OfflineCharacterData* pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter((*iter).charId);
		if (nullptr == pOffline)	continue;
		(*iter).charLv = pOffline->GetLevel();
		if ((*iter).charId == charId)
			charInfo = &(*iter);
	}
	return charInfo;*/
	for (LOSTCITYSOCRE_VEC::iterator iter = vec.begin(); iter != vec.end(); ++iter)
	{
		if ((*iter).charId == charId)
			return &(*iter);
	}
	return nullptr;
}

LostCityUnionInfo* UnionMgr::GetLostCity(uint32_t unionId)
{
	if (unionId == mLostCity[ECamp_Type_Light].unionId)
	{
		return &mLostCity[ECamp_Type_Light];
	}
	if (unionId == mLostCity[ECamp_Type_Dark].unionId)
	{
		return &mLostCity[ECamp_Type_Dark];
	}
	return nullptr;
}

void UnionMgr::GetLostCityInfo(CharIDType charId, ActivityLostCityInfoRsp& rsp)
{
	LostCityUnionInfoProto *lightInfo = rsp.mutable_light_union_info();
	LostCityUnionInfoProto *darkInfo = rsp.mutable_dark_union_info();
	CUnion *pLightUnion = g_GetUnionMgr()->GetUnion(mLostCity[ECamp_Type_Light].unionId);
	CUnion *pDarkUnion = g_GetUnionMgr()->GetUnion(mLostCity[ECamp_Type_Dark].unionId);
	if (nullptr == pLightUnion || nullptr == pDarkUnion)
	{
		rsp.set_ret(RET_FAIL);
		return;
	}
	lightInfo->set_union_name(pLightUnion->Name());
	lightInfo->set_leader_name(pLightUnion->LeaderName());
	lightInfo->set_union_lv(pLightUnion->Level());
	lightInfo->set_union_mem(pLightUnion->MemberCount());
	lightInfo->set_fight(pLightUnion->Fight());
	lightInfo->set_score(mLostCity[ECamp_Type_Light].score);
	lightInfo->set_icon_id(pLightUnion->IconId());

	darkInfo->set_union_name(pDarkUnion->Name());
	darkInfo->set_leader_name(pDarkUnion->LeaderName());
	darkInfo->set_union_lv(pDarkUnion->Level());
	darkInfo->set_union_mem(pDarkUnion->MemberCount());
	darkInfo->set_fight(pDarkUnion->Fight());
	darkInfo->set_score(mLostCity[ECamp_Type_Dark].score);
	darkInfo->set_icon_id(pDarkUnion->IconId());

	uint32_t rank = 0;
	for (LOSTCITYSOCRE_VEC::iterator ib = mLostCity[ECamp_Type_Light].scoreVec.begin(), ie = mLostCity[ECamp_Type_Light].scoreVec.end(); ib != ie; ++ib)
	{
		LostCityCharInfoProto *charInfo = rsp.add_light_char_info();
		charInfo->set_rank(++rank);
		charInfo->set_char_name((*ib).charName);
		charInfo->set_kill_score((*ib).killValue);
		charInfo->set_convoy_score((*ib).convoyValue);
		charInfo->set_total_score((*ib).totalValue);
	}
	rank = 0;
	for (LOSTCITYSOCRE_VEC::iterator ib = mLostCity[ECamp_Type_Dark].scoreVec.begin(), ie = mLostCity[ECamp_Type_Dark].scoreVec.end(); ib != ie; ++ib)
	{
		LostCityCharInfoProto *charInfo = rsp.add_dark_char_info();
		charInfo->set_rank(++rank);
		charInfo->set_char_name((*ib).charName);
		charInfo->set_kill_score((*ib).killValue);
		charInfo->set_convoy_score((*ib).convoyValue);
		charInfo->set_total_score((*ib).totalValue);
	}
}

void UnionMgr::ClearLostCity()
{
	mLostCity[ECamp_Type_Light].Clear();
	mLostCity[ECamp_Type_Dark].Clear();
}

void UnionMgr::GetLostCityUnion(uint32_t &lightUnionId, uint32_t &darkUnionId)
{
	lightUnionId = mLostCity[ECamp_Type_Light].unionId;
	darkUnionId = mLostCity[ECamp_Type_Dark].unionId;
}

void UnionMgr::AddScore(LostCityCharInfo &charInfo, LostCityUnionInfo &unionInfo, uint32_t eventType, uint32_t scoreValue)
{
	if (eventType == EventLostCity_Kill || eventType == EventLostCity_KillBoss)
		charInfo.killValue += scoreValue;
	else
		charInfo.convoyValue += scoreValue;
	charInfo.totalValue += scoreValue;
	unionInfo.score += scoreValue;
}

inline bool cmp(const LostCityCharInfo &L1, const LostCityCharInfo &L2)
{
	if (L1.totalValue == L2.totalValue)
	{
		if (L1.killValue == L2.killValue)
		{
			if (L1.convoyValue == L2.convoyValue)
			{
				if (L1.charLv == L2.charLv)
					return true;
				else
					return L1.charLv > L2.charLv;
			}
			else
				return L1.convoyValue > L2.convoyValue;
		}
		else
			return L1.killValue > L2.killValue;
	}
	else
		return L1.totalValue > L2.totalValue;
	return true;
}

void UnionMgr::OnScoreChange(uint32_t unionId, CharIDType charId, uint32_t eventType, uint32_t scoreValue)	//遗失之城积分变动
{
	if (unionId != mLostCity[ECamp_Type_Light].unionId && unionId != mLostCity[ECamp_Type_Dark].unionId)
	{
		LogErrFmtPrint("[center] UnionMgr::OnScoreChange... unionId is wrong...unionId:%d,mLightUnionId:%d,mDarkUnionId:%d", unionId, mLostCity[ECamp_Type_Light].unionId, mLostCity[ECamp_Type_Dark].unionId);
		return;
	}
	LostCityUnionInfo &unionInfo = (unionId == mLostCity[ECamp_Type_Light].unionId) ? mLostCity[ECamp_Type_Light] : mLostCity[ECamp_Type_Dark];
	LostCityCharInfo *charInfo = FindCityScore(unionInfo.scoreVec, charId);
	if (nullptr != charInfo)
	{
		AddScore(*charInfo, unionInfo, eventType, scoreValue);
	}
	else
	{
		OfflineCharacterData* pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
		if (nullptr == pOffline)
		{
			LogErrFmtPrint("[center] UnionMgr::OnScoreChange... pOffline = nullptr...charId:%lu", charId);
			return;
		}
		LostCityCharInfo newScore;
		newScore.charId = pOffline->GetCharID();
		newScore.charName = pOffline->GetCharName();
		newScore.charLv = pOffline->GetLevel();
		AddScore(newScore, unionInfo, eventType, scoreValue);
		unionInfo.scoreVec.push_back(newScore);
	}
	sort(unionInfo.scoreVec.begin(), unionInfo.scoreVec.end(), cmp);
}

void UnionMgr::LostCityCalc()
{
	if (mLostCity[ECamp_Type_Light].unionId <= 0 || mLostCity[ECamp_Type_Dark].unionId <= 0)
	{
		LogErrFmtPrint("[center] UnionMgr::LostCityCalc... faild because no union win");
		return;
	}

	for (LOSTCITYSOCRE_VEC::iterator ib = mLostCity[ECamp_Type_Light].scoreVec.begin(), ie = mLostCity[ECamp_Type_Light].scoreVec.end(); ib != ie; ++ib)
	{
		//遗失之城活动结束 清除遗失之城商铺购买次数 清楚遗失之城领取奖励标识(这些都是活动结束重置) 同时累计遗失之城历史积分
		LostCityCharInfo &charInfo = *ib;
		charInfo.buyTimes = 0;
		charInfo.isGet = false;
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charInfo.charId);
		if (nullptr == pOffline)	continue;
		pOffline->SetLostCityVal(pOffline->GetLostCityVal() + charInfo.totalValue);
		AddCharOfflineSave(charInfo.charId);
		NotifyLostCityAwards(charInfo.charId);
	}
	for (LOSTCITYSOCRE_VEC::iterator ib = mLostCity[ECamp_Type_Dark].scoreVec.begin(), ie = mLostCity[ECamp_Type_Dark].scoreVec.end(); ib != ie; ++ib)
	{
		//遗失之城活动结束 清除遗失之城商铺购买次数 清楚遗失之城领取奖励标识(这些都是活动结束重置) 同时累计遗失之城历史积分
		LostCityCharInfo &charInfo = *ib;
		charInfo.buyTimes = 0;
		charInfo.isGet = false;
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charInfo.charId);
		if (nullptr == pOffline)	continue;
		pOffline->SetLostCityVal(pOffline->GetLostCityVal() + charInfo.totalValue);
		AddCharOfflineSave(charInfo.charId);
		NotifyLostCityAwards(charInfo.charId);
	}
}

void UnionMgr::EnterLostCity(CharIDType charId)
{
	//根据遗失之城活动数据判断能否进入地宫副本
	ActivityLostCityEnterRsp rsp;
	uint32_t winUnionId = GetWinUnionId();
	if (winUnionId <= 0)
	{
		rsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_ENTER, &rsp);
		return;
	}
	uint32_t unionId = GetCharUnionId(charId);
	if (unionId != winUnionId)
	{
		rsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_ENTER, &rsp);
		return;
	}

	//TODO 进入遗失之城地宫 是这个接口吗?
	int32_t retCode = g_GetCenterDuplicateMgr()->canEnterUnionDungeon(charId);
	if (RET_SUCCESS == retCode)
	{
		g_GetCenterDuplicateMgr()->enterUnionDungeon(charId);
	}
	rsp.set_ret(retCode);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_ENTER, &rsp);
}

void UnionMgr::LostCityGetAwards(CharIDType charId, uint32_t type, uint32_t exchangeId/*等于0:领取奖励 大于0:兑换称号*/)
{
	ActivityLostCityAwardsUpdate rsp;
	rsp.set_retcode(RET_FAIL);

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		rsp.set_retcode(RET_NOT_HAVE_CHARACTER);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
		return;
	}
	uint32_t unionId = GetCharUnionId(charId);
	if (unionId <= 0)
	{
		rsp.set_retcode(RET_UNION_NOT_JOIN);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
		return;
	}
	//公会战无人参与
/*
	if (mLostCity[ECamp_Type_Light].score == 0 && mLostCity[ECamp_Type_Dark].score == 0)
	{
		rsp.set_retcode(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
		return;
	}*/
	if (unionId != mLostCity[ECamp_Type_Light].unionId && unionId != mLostCity[ECamp_Type_Dark].unionId)
	{
		//LogErrFmtPrint("[center] UnionMgr::OnScoreChange... unionId is wrong...unionId:%d,mLightUnionId:%d,mDarkUnionId:%d", unionId, mLostCity[ECamp_Type_Light].unionId, mLostCity[ECamp_Type_Dark].unionId);
		rsp.set_retcode(RET_ACTIVITY_LOST_CITY_REWAED_ERROR);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
		return;
	}
	LostCityUnionInfo &unionInfo = (unionId == mLostCity[ECamp_Type_Light].unionId) ? mLostCity[ECamp_Type_Light] : mLostCity[ECamp_Type_Dark];
	LostCityCharInfo* charInfo = FindCityScore(unionInfo.scoreVec, charId);
	if (nullptr == charInfo)
	{
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
		return;
	}

	UnionChar *pUnionChar = CharUnionData(charId);
	if (nullptr == pUnionChar)
	{
		rsp.set_retcode(RET_UNION_NOT_JOIN);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
		return;
	}

	if (type == 1)	//领取奖励
	{
		if (charInfo->isGet)
		{
			rsp.set_retcode(RET_HUOYUEDU_HAVE_REWARD);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
			return;
		}
		const GuildGuildwarCfgMap *pAwardMap = g_GetGuildGuildwarCfgTable()->GetGuildGuildwarCfgMap(); 
		if (nullptr == pAwardMap)
		{
			rsp.set_retcode(RET_CONFIG_ERROR);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
			return;
		}
		uint32_t itemId = 0;
		int32_t tempValue = 0;
		for (GuildGuildwarCfgMap::const_iterator ib = pAwardMap->begin(), ie = pAwardMap->end(); ib != ie; ++ib)
		{
			const GuildGuildwarCfgInfo &awardInfo = ib->second;
			if ((uint32_t)awardInfo.scoreType == type && charInfo->totalValue >= (uint32_t)awardInfo.priceScore && awardInfo.priceScore >= tempValue)
			{
				itemId = awardInfo.relateId;
				tempValue = awardInfo.priceScore;
			}
		}
		if (itemId <= 0)
		{
			rsp.set_retcode(RET_ACTIVITY_LOST_CITY_LESS_SCORE);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
			return;
		}
		//charInfo->totalValue = 0;
		charInfo->isGet = true;

		CLActivityGetReward notify;
		notify.set_charid(charId);
		notify.set_itemid(itemId);
		notify.set_itemnum(1);
		notify.set_rewardtype(ENotifyType_Item_LostCity);
		g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_ACTIVITY, CENTER_TO_LOGIC_ACTIVITY_GETREWARD, &notify);
	}
	else	//兑换称号
	{
		const GuildGuildwarCfgInfo *pAwardInfo = g_GetGuildGuildwarCfgTable()->GetGuildGuildwarCfgInfo(exchangeId);
		if (nullptr == pAwardInfo)
		{
			rsp.set_retcode(RET_CONFIG_ERROR);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
			return;
		}
		if (pOffline->GetLostCityVal() < (uint32_t)pAwardInfo->priceScore)
		{
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
			return;
		}
		VEC_INT32 &titleVec = pUnionChar->GetTitle();
		VEC_INT32::iterator iter = find(titleVec.begin(), titleVec.end(), pAwardInfo->relateId);
		if (iter != titleVec.end())
		{
			rsp.set_retcode(RET_ACTIVITY_LOST_CITY_TITLE_ERROR);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
			return;
		}

		titleVec.push_back(pAwardInfo->relateId);

		pOffline->SetLostCityVal(pOffline->GetLostCityVal() - pAwardInfo->priceScore);
		AddCharOfflineSave(charId);
		//pUnionChar->SetLostCityVal(pUnionChar->GetLostCityVal() - pAwardInfo->priceScore);

		CLActivityGetReward notify;
		notify.set_charid(charId);
		notify.set_titleid(pAwardInfo->relateId);
		g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_ACTIVITY, CENTER_TO_LOGIC_ACTIVITY_GETREWARD, &notify);
	}

	rsp.set_retcode(RET_SUCCESS);
	rsp.set_score(charInfo->totalValue);
	rsp.set_total_score(pOffline->GetLostCityVal());
	rsp.set_is_get(charInfo->isGet);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ACTIVITY, CENTER_TO_CLIENT_ACTIVITY_LOST_CITY_AWARDS, &rsp);
}

void UnionMgr::SetAllUnionFight(std::vector<RankingListClanData>& vClan)	//填充所有工会的战力
{
	UnionMap::iterator iter = m_mapUnion.begin();
	for (; iter != m_mapUnion.end(); ++iter)
	{
		CUnion *pUnion = iter->second;
		if (nullptr != pUnion)
		{
			RankingListClanData protoData;
			protoData.set_clanname(pUnion->Name());
			protoData.set_clanleadername(pUnion->LeaderName());
			protoData.set_fightvalue(pUnion->UnionFight());
			protoData.set_camp(pUnion->CampId());
			vClan.push_back(protoData);
		}
	}
}

void UnionMgr::GetUnionParamForRank(CharIDType cid, string &strUnionName, string &strLeaderName, uint32_t &canUseContri, uint32_t &weekContri)//获取排行所需要的工会参数
{
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(cid);
	if (nullptr == pOffline)
	{
		return;
	}
	canUseContri = pOffline->GetUnionUseContri();
	//
	CUnion *pUnion = GetCharUnion(cid);
	if (nullptr != pUnion)
	{
		strUnionName = pUnion->Name();
		strLeaderName = pUnion->LeaderName();
		weekContri = pUnion->GetMemWeekContri(cid);
	}	
}


uint32_t UnionMgr::GetSceneIdByType(uint32_t unionId, int8_t sceneType) //根据工会相关的场景类型获取场景ID
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr == pUnion)
	{
		return 0;
	}
	return pUnion->SceneIdByType(sceneType);
}

void UnionMgr::OnUnionActPreStart(int8_t actType, uint32_t activityId) //工会活动开始之前的处理
{
	_UNUSE(activityId);
	//TODO 遗失之城活动开启之前  需要先关闭工会地宫副本
	if (ATI_LOST_CITY == actType)
	{
		uint32_t unionId = GetWinUnionId();//获取工会战第一名的工会ID
		uint32_t dungeonSceneId = GetSceneIdByType(unionId, EUnionSceneType_DunGeon);
		if (dungeonSceneId > 0)
		{
			uint32_t dungeonLogicId = g_GetCenterDuplicateMgr()->dupSceneLogic(dungeonSceneId);
			//工会活动场景结束
			g_GetCenterDuplicateMgr()->unionActEnd(dungeonSceneId);
			//通知逻辑服 关闭地宫
			NotifyLogicDungeonClose(unionId, dungeonSceneId, dungeonLogicId);
		}
	}
}

void UnionMgr::OnUnionActStart(int8_t actType,uint32_t activityId)	//工会活动开始
{
	
	if (ATI_CLOUD == actType) //云端试炼
	{
		//需要清空工会积分数据
		UnionMap::iterator iter = m_mapUnion.begin();
		for (; iter != m_mapUnion.end(); ++iter)
		{
			CUnion *pUnion = iter->second;
			if (nullptr != pUnion)
			{
				pUnion->ClearCloudScore();
				//
				SET_UINT64 setMember;
				pUnion->AllMember(setMember);
				BroadCastCloudOpen(setMember);
			}
		}
		//清空排名
		ClearScoreRank();
	}
	else if (ATI_GOBLIN == actType || ATI_ANCIENT_ELF == actType) //哥布林或者远古精灵
	{
		UnionMap::iterator iter = m_mapUnion.begin();
		for (; iter != m_mapUnion.end(); ++iter)
		{
			CUnion *pUnion = iter->second;
			if (nullptr != pUnion)
			{
				uint32_t unionSceneId = pUnion->UnionSceneId();
				if (unionSceneId > 0)
				{
					uint32_t sceneLogicId = g_GetCenterDuplicateMgr()->dupSceneLogic(unionSceneId);
					//通知逻辑服 活动 状态
					//NotifyLogicActState(pUnion->UnionId(), unionSceneId, sceneLogicId, activityId, 1, pUnion->EliteAverageLev());
					SUnionActParam param;
					pUnion->GetActParam(param);
					param.actScene = unionSceneId;
					NotifyLogicActState(sceneLogicId, activityId,1, param);
				}

				SET_UINT64 setMember;
				pUnion->AllMember(setMember);
				if (ATI_GOBLIN == actType)
				{
					BroadCastGoblinAppear(setMember);
				}
				else if (ATI_ANCIENT_ELF == actType)
				{
					BroadCastAncientElfApprear(setMember);
				}

			}
		}
	}
	else if (ATI_LOST_CITY == actType)	//遗失之城活动
	{
		mLostCity[ECamp_Type_Light].Clear();
		mLostCity[ECamp_Type_Dark].Clear();

		//取云端试炼的活动结果,光明和黑暗阵营公会的最终胜方有权限参加遗失之城活动
		SET_UINT32 iset;
		CloudFirstRank(mLostCity[ECamp_Type_Light].unionId, mLostCity[ECamp_Type_Dark].unionId);

		CUnion *pLightUnion = g_GetUnionMgr()->GetUnion(mLostCity[ECamp_Type_Light].unionId);
		CUnion *pDarkUnion = g_GetUnionMgr()->GetUnion(mLostCity[ECamp_Type_Dark].unionId);
		if (nullptr == pLightUnion)
		{
			LogInfoFmtPrint("[center] UnionMgr::OnUnionActStart... LostCity Activity less union, lightUnionId=%d", mLostCity[ECamp_Type_Light].unionId);
			return;
		}
		if (nullptr == pDarkUnion)
		{
			LogInfoFmtPrint("[center] UnionMgr::OnUnionActStart... LostCity Activity less union, darkUnion=%d, ", mLostCity[ECamp_Type_Dark].unionId);
			return;
		}

		SET_UINT64 lightMem;
		pLightUnion->AllMember(lightMem);
		SET_UINT64 darkMem;
		pDarkUnion->AllMember(darkMem);

		for (SET_UINT64::iterator ib = lightMem.begin(), ie = lightMem.end(); ib != ie; ++ib)
		{
			OfflineCharacterData* pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(*ib);
			if (nullptr == pOffline)	continue;
			LostCityCharInfo newScore;
			newScore.charId = pOffline->GetCharID();
			newScore.charName = pOffline->GetCharName();
			newScore.charLv = pOffline->GetLevel();
			mLostCity[ECamp_Type_Light].scoreVec.push_back(newScore);
		}
		sort(mLostCity[ECamp_Type_Light].scoreVec.begin(), mLostCity[ECamp_Type_Light].scoreVec.end(), cmp);
		for (SET_UINT64::iterator ib = darkMem.begin(), ie = darkMem.end(); ib != ie; ++ib)
		{
			OfflineCharacterData* pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(*ib);
			if (nullptr == pOffline)	continue;
			LostCityCharInfo newScore;
			newScore.charId = pOffline->GetCharID();
			newScore.charName = pOffline->GetCharName();
			newScore.charLv = pOffline->GetLevel();
			mLostCity[ECamp_Type_Dark].scoreVec.push_back(newScore);
		}
		sort(mLostCity[ECamp_Type_Dark].scoreVec.begin(), mLostCity[ECamp_Type_Dark].scoreVec.end(), cmp);
	}
}

void UnionMgr::OnUnionActStop(int8_t actType, uint32_t activityId) //工会活动结束
{
	MAP_UINT32_UINT32 mapUnionActScene;
	mapUnionActScene.clear();
	if (ATI_CLOUD == actType) //云端试炼
	{
		//需要通知云端试炼结束
		UnionMap::iterator iter = m_mapUnion.begin();
		for (; iter != m_mapUnion.end(); ++iter)
		{
			CUnion *pUnion = iter->second;
			if (nullptr != pUnion)
			{
				uint32_t cloudSceneId = pUnion->CloudSceneId();
				if (cloudSceneId > 0)
				{
					mapUnionActScene[pUnion->UnionId()] = cloudSceneId;
					//云端试炼副本结束
					g_GetCenterDuplicateMgr()->unionActEnd(cloudSceneId);
				}
			}
		}
	}
	else if (ATI_GOBLIN == actType || ATI_ANCIENT_ELF == actType )  //哥布林或者远古精灵
	{
		UnionMap::iterator iter = m_mapUnion.begin();
		for (; iter != m_mapUnion.end(); ++iter)
		{
			CUnion *pUnion = iter->second;
			if (nullptr != pUnion)
			{
				if (pUnion->UnionSceneId() > 0)
				{
					mapUnionActScene[pUnion->UnionId()] = pUnion->UnionSceneId();
				}
			}
		}
	}
	else if (ATI_LOST_CITY == actType)	//遗失之城
	{
		//mLostCity[ECamp_Type_Light].Clear();
		//mLostCity[ECamp_Type_Dark].Clear();
		LostCityCalc();
	}

	MAP_UINT32_UINT32::iterator iterScene = mapUnionActScene.begin();
	for (; iterScene != mapUnionActScene.end(); ++iterScene)
	{
		uint32_t sceneLogicId = g_GetCenterDuplicateMgr()->dupSceneLogic(iterScene->second);
		//通知逻辑服 活动 结束
		CUnion *pUnion = GetUnion(iterScene->first);
		if (nullptr != pUnion)
		{
			SUnionActParam param;
			pUnion->GetActParam(param);
			param.actScene = iterScene->second;
			NotifyLogicActState(sceneLogicId, activityId,0, param);
		}			
	}
}


void UnionMgr::OnCloudScore(uint32_t unionId, int32_t pass, uint64_t addScore, const UnionAllCloudScoreProto &scoreProto)		//云端试炼积分
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr == pUnion)
	{
		return;
	}
	//增加云端试炼积分信息
	pUnion->AddCloudScore(addScore, pass, scoreProto);
	//每个工会设置积分之后，再进行排名
	MAP_UINT64_INT32 mapCharScore;
	pUnion->MemCloudScore(mapCharScore);
	uint64_t totalScore = pUnion->TotalScore();
	UpdateCloudScore(unionId, totalScore, mapCharScore);
	if (pass)//通关
	{
		LogDebugFmtPrint("[center] UnionMgr::OnCloudScore....unionid:%u, totalScore:%u ",unionId,totalScore);
		//通知工会所有成员，云端试炼副本已通关
		SET_UINT64 setMember;
		pUnion->AllMember(setMember);
		SET_UINT64::iterator iterMem = setMember.begin();
		for (; iterMem != setMember.end(); ++iterMem)
		{
			SyncUnionInfo((*iterMem));
		}
	}	
}

void UnionMgr::CloudFirstRank(uint32_t &lightUnionId, uint32_t &darkUnionId) //云端试炼中排名第一的不同阵营工会
{
	uint32_t result[ECamp_Type_Limit] = { 0 };

	int32_t rankSize = m_vecUnionRank.size();
	VecScoreRank::iterator iter = m_vecUnionRank.begin();
	for (int32_t i = 0; i < rankSize; ++i)
	{
		SUnionScoreRank &stRank = m_vecUnionRank[i];
		CUnion *pUnion = GetUnion(stRank.rankId);
		if (nullptr != pUnion)
		{
			if (ECamp_Type_Light == pUnion->CampId() && result[ECamp_Type_Light] <= 0)
			{
				//如果是光明阵营工会，并且还没找到光明阵营排名第一的工会
				result[ECamp_Type_Light] = pUnion->UnionId();
				lightUnionId = pUnion->UnionId();
			}
			else if (ECamp_Type_Dark == pUnion->CampId() && result[ECamp_Type_Dark] <= 0)
			{
				result[ECamp_Type_Dark] = pUnion->UnionId();
				darkUnionId = pUnion->UnionId();
			}
		}
		if (result[ECamp_Type_Light] > 0 && result[ECamp_Type_Dark] > 0)
		{
			//光明和黑暗阵营 排名第一的工会已经取到了
			break;
		}
	}


	/*//这里是测试用的工会，随便取光明和黑暗阵营的工会
	UnionMap::iterator iterUnion = m_mapUnion.begin();
	for (; iterUnion != m_mapUnion.end(); ++iterUnion)
	{
		CUnion *pUnion = iterUnion->second;
		if (nullptr != pUnion)
		{
			if (ECamp_Type_Light == pUnion->CampId() && result[ECamp_Type_Light] <= 0)
			{
				result[ECamp_Type_Light] = pUnion->UnionId();
				lightUnionId = pUnion->UnionId();
			}
			else if (ECamp_Type_Dark == pUnion->CampId() && result[ECamp_Type_Dark] <= 0)
			{
				result[ECamp_Type_Dark] = pUnion->UnionId();
				darkUnionId = pUnion->UnionId();
			}
		}
		if (result[ECamp_Type_Light] > 0 && result[ECamp_Type_Dark] > 0)
		{
			break;
		}
	}*/
}

void UnionMgr::SetUnionScoreRankProto(UnionAllScoreRankProto &proto)
{
	int32_t isize = m_vecUnionRank.size();
	for (int32_t i = 0; i < isize; ++i)
	{
		const SUnionScoreRank &rank = m_vecUnionRank.at(i);
		CUnion *pUnion = GetUnion(rank.rankId);
		if (nullptr != pUnion)
		{
			UnionScoreRankProto *protoSingle = proto.add_rank();
			if (nullptr != protoSingle)
			{
				protoSingle->set_name(pUnion->Name());
				protoSingle->set_rank(i + 1);
				protoSingle->set_score(rank.rankScore);
				protoSingle->set_lev(pUnion->Level());
				protoSingle->set_camp(pUnion->CampId());
			}
		}
	}
}

void UnionMgr::SetCharScoreRankProto(UnionAllCharScoreRankProto &proto)
{
	int32_t isize = m_vecCharRank.size();
	for (int32_t i = 0; i < isize; ++i)
	{
		const SUnionScoreRank &rank = m_vecCharRank.at(i);
		CUnion *pUnion = GetCharUnion(rank.rankId);
		if (nullptr != pUnion)
		{
			UnionCharScoreRankProto *protoSingle = proto.add_rank();
			if (nullptr != protoSingle)
			{
				protoSingle->set_union_id(pUnion->UnionId());
				protoSingle->set_union_name(pUnion->Name());
				protoSingle->set_score(rank.rankScore);
				protoSingle->set_rank(i + 1);
				OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(rank.rankId);
				if (nullptr != pOffline)
				{
					protoSingle->set_lev(pOffline->GetLevel());
					protoSingle->set_name(pOffline->GetCharName());
					protoSingle->set_camp(pOffline->GetCampID());
				}				
			}
		}
	}
}

void UnionMgr::OnGoblinMonsAllDie(uint32_t unionId) //哥布林活动 怪物全部死亡
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr != pUnion)
	{
		SET_UINT64 setMember;
		pUnion->AllMember(setMember);
		BroadCastKillAllGoblin(setMember);
	}
}

void UnionMgr::OnGoblinStealMoney(uint32_t unionId, int32_t money)	//哥布林偷取工会资金
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr != pUnion)
	{
		pUnion->StealMoney(money);
		//
		SET_UINT64 setMember;
		pUnion->AllMember(setMember);
		BroadCastStealMoney(setMember, money);
	}
}

void UnionMgr::OnUnionShopFresh(uint32_t unionId)	//工会商城刷新
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr != pUnion)
	{
		pUnion->ShopFresh();
	}
}
void UnionMgr::OnUnionShopBuy(uint32_t unionId)		//工会商城购买
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr != pUnion)
	{
		pUnion->ShopBuy();
	}
}

void UnionMgr::AddCharOfflineSave(CharIDType charId)
{
	m_setCharOfflineSave.insert(charId);
}

void UnionMgr::DelCharOfflineSave(CharIDType charId)
{
	m_setCharOfflineSave.erase(charId);
}

bool UnionMgr::IsNeedSaveCharOffline(CharIDType charId)
{
	SET_UINT64::iterator iter = m_setCharOfflineSave.find(charId);
	return (iter != m_setCharOfflineSave.end()) ? true : false;
}

void UnionMgr::LoadCharUnionDataDBRet(CharUnionDBReponse &rsp)
{
	CharIDType charId = rsp.charid();
	UnionChar *pCharUnion = CharUnionData(charId);
	if (nullptr == pCharUnion)
	{
		pCharUnion = MakeUnionChar();
		if (nullptr == pCharUnion)
		{
			LogErrFmtPrint("[center] UnionMgr::LoadCharUnionDataDBRet...nullptr == pCharUnion charid:%lllu ", charId);
			return;
		}
		pCharUnion->Init(charId);
		m_mapUnionChar[charId] = pCharUnion;
	}
	if (rsp.has_data())
	{
		pCharUnion->LoadData(rsp.data());
	}
	NotifyLostCityAwards(charId, true);
}

void UnionMgr::LoadAllUnionDataDBRet(UnionDBResponse &rsp)
{
	int32_t offset = rsp.offset();
	int32_t size = rsp.union_info_size();
	bool bFlag = true;
	for (int32_t i = 0; i < size; ++i)
	{
		const UnionDBData &protoUnion = rsp.union_info(i);
		uint32_t unionID = protoUnion.union_id();
		if (GetUnion(unionID))
		{
			bFlag = false;
			MMOLOG_FMT_ERROR("[center] LoadAllUnionDataDBRet already loaded...unionId:%u ", unionID);
			break;
		}
		string strName = protoUnion.name();
		if (GetUnionByName(strName.c_str()))
		{
			bFlag = false;
			MMOLOG_FMT_ERROR("[center] LoadAllUnionDataDBRet already loaded...unionId:%u, name:%s ", unionID, strName.c_str());
			break;
		}
		CharIDType leaderId = protoUnion.leader_id();
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(leaderId);
		if (nullptr == pOffline)
		{
			MMOLOG_FMT_ERROR("[center] LoadAllUnionDataDBRet nullptr == pOffline...unionId:%u, name:%s, leaderid:%llu ", unionID, strName.c_str(), leaderId);
			break;
		}

		CUnion *pNewUnion = MakeUnion();
		if (nullptr == pNewUnion)
		{
			bFlag = false;
			MMOLOG_FMT_ERROR("[center] LoadAllUnionDataDBRet nullptr == pNewUnion...unionId:%u ,name:%s ", unionID, strName.c_str());
			break;
		}
		if (!pNewUnion->LoadUnion(unionID, leaderId, pOffline->GetCharName(), strName.c_str(), protoUnion))
		{
			FreeUnion(pNewUnion);
			bFlag = false;
			MMOLOG_FMT_ERROR("[center] LoadAllUnionDataDBRet pNewUnion->LoadUnion return false...unionId:%u ,name:%s,leaderid:%llu ", unionID, strName.c_str(),leaderId);
			break;
		}

		m_mapUnion[unionID] = pNewUnion;
		m_mapUnionByName[strName] = pNewUnion;
		m_vecUnionId.push_back(unionID);
		uint32_t nIndex = UnionIdx(unionID);
		if (m_maxUnionUid < nIndex)
		{
			m_maxUnionUid = nIndex;
		}
	}
	if (bFlag)
	{
		/*if (size >= (int32_t)MAX_UNION_DATA_COUNT_PER_LOAD)
		{
			offset += size;
			UnionDBRequest req;
			req.set_offset(offset);
			req.set_retnum((int32_t)MAX_UNION_DATA_COUNT_PER_LOAD);
			if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_ALL_UNION_DATA_REQ, &req))
			{
				MMOLOG_FMT_ERROR("[center] LoadAllUnionDataDBRet SendDataToDBProxy failed...offset:%d ", offset);
			}
		}
		else
		{
			//已经加载完成
			uint64_t nNowTime = g_GetGlobalServerTime()->UnixSec();
			uint64_t nInterTime = nNowTime - m_startLoad;

			//设置加载完成
			//m_finishLoad = true;
			int32_t nTotal = (int32_t)m_mapUnion.size();
			MMOLOG_FMT_INFO("[center] LoadAllUnionDataDBRet finished.... total_count:%d , total_sec:%lld,m_maxUnionUid:%u  ", nTotal, nInterTime, m_maxUnionUid);

			//加载完所有工会DB数据
			OnFinishLoadAllUnionDBData();


			//工会数据加载完成之后，开始加载玩家工会离线数据
			m_startLoad = nNowTime;
			CharUnionDBOfflineRequest req;
			req.set_offset(0);
			req.set_retnum((int32_t)MAX_CHAR_UNION_OFFLINE_DATA_COUNT_PER_LOAD);
			if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_ALL_CHAR_UNION_OFFLINE_REQ, &req))
			{
				MMOLOG_FMT_ERROR("[center] begin load char union offline data... SendDataToDBProxy failed...offset:%d ", offset);
			}
		}*/

		if (size > 0)
		{
			LogInfoFmtPrint("LoadAllUnionDataDBRet...offset:%d, size:%d ", offset, size);
			offset += size;
			UnionDBRequest req;
			req.set_offset(offset);
			if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_ALL_UNION_DATA_REQ, &req))
			{
				MMOLOG_FMT_ERROR("[center] LoadAllUnionDataDBRet SendDataToDBProxy failed...offset:%d ", offset);
			}
		}
		else
		{
			//已经加载完成
			uint64_t nNowTime = g_GetGlobalServerTime()->UnixSec();
			uint64_t nInterTime = nNowTime - m_startLoad;

			//设置加载完成
			//m_finishLoad = true;
			int32_t nTotal = (int32_t)m_mapUnion.size();
			MMOLOG_FMT_INFO("[center] LoadAllUnionDataDBRet finished.... total_count:%d , total_sec:%lld,m_maxUnionUid:%u  ", nTotal, nInterTime, m_maxUnionUid);

			//加载完所有工会DB数据
			OnFinishLoadAllUnionDBData();


			//工会数据加载完成之后，开始加载玩家工会离线数据
			m_startLoad = nNowTime;
			CharUnionDBOfflineRequest req;
			req.set_offset(0);
			if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_ALL_CHAR_UNION_OFFLINE_REQ, &req))
			{
				MMOLOG_FMT_ERROR("[center] begin load char union offline data... SendDataToDBProxy failed...offset:%d ", offset);
			}
		}

	}
}

void UnionMgr::LoadAllCharUnionOfflineDataDBRet(CharUnionDBOfflineResponse &rsp)
{
	int32_t offset = rsp.offset();
	int32_t size = rsp.data_size();
	bool bFlag = true;
	for (int32_t i = 0; i < size; ++i)
	{
		const CharUnionDBOfflineInfo &protoDBOfflineInfo = rsp.data(i);
		CharIDType charId = protoDBOfflineInfo.charid();
		const CharUnionDBOfflineData &protoOfflineData = protoDBOfflineInfo.offline_data();
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
		if (nullptr == pOffline)
		{
			//出错，删除DB
			DelCharUnionData(charId);
			LogErrFmtPrint("[center] LoadAllCharUnionOfflineDataDBRet....nullptr == pOffline...charid:%llu ", charId);
			continue;
		}
		pOffline->SetUnionUseContri(protoOfflineData.use_contri());
		pOffline->SetHistoryContri(protoOfflineData.history_contri());
		pOffline->SetLostCityVal(protoOfflineData.lost_city_val());
	}
	if (bFlag)
	{
		/*if (size >= (int32_t)MAX_CHAR_UNION_OFFLINE_DATA_COUNT_PER_LOAD)
		{
			offset += size;
			CharUnionDBOfflineRequest req;
			req.set_offset(offset);
			req.set_retnum((int32_t)MAX_CHAR_UNION_OFFLINE_DATA_COUNT_PER_LOAD);
			if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_ALL_CHAR_UNION_OFFLINE_REQ, &req))
			{
				MMOLOG_FMT_ERROR("[center] LoadAllCharUnionOfflineDataDBRet SendDataToDBProxy failed...offset:%d ", offset);
			}
		}
		else
		{
			//已经加载完成
			uint64_t nNowTime = g_GetGlobalServerTime()->UnixSec();
			uint64_t nInterTime = nNowTime - m_startLoad;

			//设置加载完成
			m_finishLoad = true;
			MMOLOG_FMT_INFO("[center] LoadAllCharUnionOfflineDataDBRet finished.... total_sec:%lld  ", nInterTime);

			//数据加载完成之后 需要创建工会驻地场景
			g_GetTimerAxis()->SetTimer(ETimer_ID_Create_UnionHome_Scene, 3 * 1000, this);
		}*/

		if (size > 0)
		{
			LogInfoFmtPrint("LoadAllCharUnionOfflineDataDBRet...offset:%d, size:%d ", offset, size);
			offset += size;
			CharUnionDBOfflineRequest req;
			req.set_offset(offset);
			if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_UNION, DBPROXY_PROTOCOL_ALL_CHAR_UNION_OFFLINE_REQ, &req))
			{
				MMOLOG_FMT_ERROR("[center] LoadAllCharUnionOfflineDataDBRet SendDataToDBProxy failed...offset:%d ", offset);
			}
		}
		else
		{
			//已经加载完成
			uint64_t nNowTime = g_GetGlobalServerTime()->UnixSec();
			uint64_t nInterTime = nNowTime - m_startLoad;

			//设置加载完成
			m_finishLoad = true;
			MMOLOG_FMT_INFO("[center] LoadAllCharUnionOfflineDataDBRet finished.... total_sec:%lld  ", nInterTime);

			//数据加载完成之后 需要创建工会驻地场景
			g_GetTimerAxis()->SetTimer(ETimer_ID_Create_UnionHome_Scene, 3 * 1000, this);
		}

	}
}

void UnionMgr::RecycleUnion(CUnion *pUnion)
{
	if (nullptr == pUnion)
	{
		return;
	}
	uint32_t unionId = pUnion->UnionId();
	string strName = pUnion->Name();
	UnionMap::iterator iter = m_mapUnion.find(unionId);
	if (iter != m_mapUnion.end())
	{
		pUnion->UnInit();
		m_mapUnion.erase(iter);
		m_mapUnionByName.erase(strName);
		VEC_UINT32::iterator iterVec = m_vecUnionId.begin();
		for (; iterVec != m_vecUnionId.end(); ++iterVec)
		{
			if (unionId == (*iterVec))
			{
				m_vecUnionId.erase(iterVec);
				break;
			}
		}
	}
	FreeUnion(pUnion);
}

void UnionMgr::RecycleUnionChar(UnionChar *pChar)	//回收工会玩家数据
{
	if (nullptr == pChar)
	{
		return;
	}
	CharIDType charId = pChar->CharId();
	UnionCharMap::iterator iter = m_mapUnionChar.find(charId);
	if (iter != m_mapUnionChar.end())
	{
		pChar->UnInit();
		m_mapUnionChar.erase(iter);
		FreeUnionChar(pChar);
	}
}

CUnion *UnionMgr::MakeUnion()
{
	if (nullptr != m_pUnionPool)
	{
		return m_pUnionPool->MallocObj();
	}
	return nullptr;
}

void UnionMgr::FreeUnion(CUnion *pUnion)
{
	if (nullptr != pUnion)
	{
		m_pUnionPool->FreeObj(pUnion);
	}
}

UnionChar *UnionMgr::MakeUnionChar()
{
	if (nullptr != m_pUnionCharPool)
	{
		return m_pUnionCharPool->MallocObj();
	}
	return nullptr;
}

void UnionMgr::FreeUnionChar(UnionChar *pChar)
{
	if (nullptr != pChar)
	{
		m_pUnionCharPool->FreeObj(pChar);
	}
}

uint32_t UnionMgr::NewUnionUid()
{
	if (m_maxUnionUid >= UINT32_MAX)
	{
		m_maxUnionUid = 0;
	}
	++m_maxUnionUid;
	//为了避免后面合服工会ID重复，这里工会ID用  自增ID + 区服ID(14位) 
	return (uint32_t)(UNION_MAKE_UID(m_maxUnionUid, g_GetCenterService()->GetZoneId()));
}

uint32_t UnionMgr::UnionIdx(uint32_t unionUid)
{
	return (uint32_t)UNION_UID_INDEX(unionUid);
}

CUnion *UnionMgr::GetUnion(uint32_t unionUid)
{
	UnionMap::iterator iter = m_mapUnion.find(unionUid);
	return (iter != m_mapUnion.end()) ? iter->second : nullptr;
}

CUnion *UnionMgr::GetUnionByName(const char *szUnionName)
{
	UnionMapByName::iterator iter = m_mapUnionByName.find(szUnionName);
	return (iter != m_mapUnionByName.end()) ? iter->second : nullptr;
}


UnionChar *UnionMgr::CharUnionData(CharIDType charId)			//玩家工会数据
{
	UnionCharMap::iterator iter = m_mapUnionChar.find(charId);
	return (iter != m_mapUnionChar.end()) ? iter->second : nullptr;
}

void UnionMgr::AddCharUnionId(CharIDType charId, uint32_t unionId)
{
	m_mapCharUnionID[charId] = unionId;
}

void UnionMgr::DelCharUnionId(CharIDType charId)
{
	m_mapCharUnionID.erase(charId);
}

uint32_t UnionMgr::GetCharUnionId(CharIDType charId)
{
	MAP_UINT64_UINT32::iterator iter = m_mapCharUnionID.find(charId);
	return (iter != m_mapCharUnionID.end()) ? iter->second : 0;
}

const string UnionMgr::GetCharUnionName(CharIDType charId)	//获取玩家所在工会名字
{
	string str = "";
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr != pUnion)
	{
		str = pUnion->Name();
	}
	return str;
}

CUnion *UnionMgr::GetCharUnion(CharIDType charId)
{
	uint32_t unionId = GetCharUnionId(charId);
	return GetUnion(unionId);
}

bool UnionMgr::ValidDuty(int8_t dutyType) //是否是有效的职位
{
	if (dutyType > EUnionDutyType_None && dutyType < EUnionDutyType_Limit)
	{
		return true;
	}
	return false;
}

bool UnionMgr::ValidJoinType(int8_t joinType) //是否是有效的加入类型
{
	if (joinType > EUnionJoinType_None && joinType < EUnionJoinType_Limit)
	{
		return true;
	}
	return false;
}

bool UnionMgr::ValidRedType(int8_t redType)		//是否是有效的红包类型
{
	if (redType > EUnionRedType_None && redType < EUnionRedType_Limit)
	{
		return true;
	}
	return false;
}

bool UnionMgr::ValidResearchType(int8_t researchType)		//是否是有效的研究类型
{
	if (researchType > EUnionResearchType_None && researchType < EUnionResearchType_Limit)
	{
		return true;
	}
	return false;
}

bool UnionMgr::ValidUnionSceneType(int8_t sceneType)	//是否是有效的工会相关的场景类型
{
	if (sceneType > EUnionSceneType_None && sceneType < EUnionSceneType_Limit)
	{
		return true;
	}
	return false;
}

SET_UINT32 *UnionMgr::GetCharApply(CharIDType charId)			//获取玩家申请列表
{
	MAP_UINT64_SET_UINT32::iterator iter = m_mapCharApply.find(charId);
	if (iter != m_mapCharApply.end())
	{
		return &iter->second;
	}
	return nullptr;
}

void UnionMgr::AddCharApply(CharIDType charId, uint32_t unionId)	//添加玩家申请
{
	SET_UINT32 *pApply = GetCharApply(charId);
	if (nullptr != pApply)
	{
		pApply->insert(unionId);
	}
	else
	{
		SET_UINT32 setApply;
		setApply.insert(unionId);
		m_mapCharApply[charId] = setApply;
	}
}

void UnionMgr::DelCharApply(CharIDType charId, uint32_t unionId)	//删除玩家申请工会列表
{
	SET_UINT32 *pApply = GetCharApply(charId);
	if (nullptr != pApply)
	{
		pApply->erase(unionId);
		if (pApply->size() == 0)
		{
			m_mapCharApply.erase(charId);
		}
	}
}

void UnionMgr::ClearCharApply(CharIDType charId)	//清空玩家所有的申请工会列表
{
	SET_UINT32 *pApply = GetCharApply(charId);
	if (nullptr != pApply)
	{
		SET_UINT32::iterator iter = pApply->begin();
		for (; iter != pApply->end(); ++iter)
		{
			uint32_t unionId = (*iter);
			CUnion *pUnion = GetUnion(unionId);
			if (nullptr != pUnion)
			{
				pUnion->DelApplyByCharId(charId);
			}
		}
		//
		pApply->clear();
		m_mapCharApply.erase(charId);
	}
}


void UnionMgr::GetUnionAllMember(uint32_t unionId, SET_UINT64 &setMember) //获取工会所有成员
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr != pUnion)
	{
		pUnion->AllMember(setMember);
	}
}

void UnionMgr::LoginSyncData(CharIDType charId, CharLoginSyncCenterData *protoLoginSync)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr != pUnion)
	{
		protoLoginSync->set_union_id(pUnion->UnionId());
		protoLoginSync->set_union_name(pUnion->Name());
		protoLoginSync->set_uinon_duty(pUnion->MemberDuty(charId));
		protoLoginSync->set_union_level(pUnion->BuildLev(EUnionBuildType_Hall));
		protoLoginSync->set_union_icon(pUnion->IconId());
		protoLoginSync->set_office_level(pUnion->BuildLev(EUnionBuildType_Office));
		protoLoginSync->set_vault_level(pUnion->BuildLev(EUnionBuildType_Vault));
		protoLoginSync->set_union_home_scene(pUnion->UnionSceneId());
	}
	else
	{
		protoLoginSync->set_union_id(0);
		protoLoginSync->set_union_name("");
		protoLoginSync->set_uinon_duty(EUnionDutyType_None);
		protoLoginSync->set_union_level(0);
		protoLoginSync->set_union_icon(0);
		protoLoginSync->set_office_level(0);
		protoLoginSync->set_vault_level(0);
		protoLoginSync->set_union_home_scene(0);
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr != pOffline)
	{
		protoLoginSync->set_union_contri(pOffline->GetUnionUseContri());
	}
}

CUnion *UnionMgr::CreateUnion(CharIDType charId, const char *szUnionName, int32_t icondId, const char *szNotice)
{
	if (nullptr == szUnionName)
	{
		return nullptr;
	}
	ActiveCharacter *pCharOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pCharOnline)
	{
		LogErrFmtPrint("[center] UnionMgr::CreateUnion....nullptr == pCharOnline....charid:%llu,szName:%s ", charId, szUnionName);
		return nullptr;
	}
	OfflineCharacterData *pCharOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pCharOffline)
	{
		LogErrFmtPrint("[center] UnionMgr::CreateUnion....nullptr == pCharOffline....charid:%llu,szName:%s ", charId, szUnionName);
		return nullptr;
	}
	CUnion *pNewUnion = MakeUnion();
	if (nullptr == pNewUnion)
	{
		LogErrFmtPrint("[center] UnionMgr::CreateUnion....nullptr == pNewUnion....charid:%llu,szName:%s ", charId, szUnionName);
		return nullptr;
	}
	uint32_t newUid = NewUnionUid();
	//这里再次校验下，避免uid重复
	if (nullptr != GetUnion(newUid))
	{
		FreeUnion(pNewUnion);
		LogErrFmtPrint("[center] UnionMgr::CreateUnion...repeated union uid ....charid:%llu,szName:%s, newuid:%u ", charId, szUnionName, newUid);
		return nullptr;
	}
	if (!pNewUnion->Init(newUid, charId, pCharOffline->GetCharName(), pCharOffline->GetCampID(), szUnionName, icondId, szNotice))
	{
		FreeUnion(pNewUnion);
		LogErrFmtPrint("[center] UnionMgr::CreateUnion...pNewUnion->Init failed....charid:%llu,szName:%s, newuid:%u ", charId, szUnionName, newUid);
		return nullptr;
	}
	//
	m_mapUnion[newUid] = pNewUnion;
	//
	if (!OnJoinUnion(pNewUnion,charId,EUnionDutyType_Leader))
	{

		m_mapUnion.erase(newUid);

		FreeUnion(pNewUnion);
		LogErrFmtPrint("[center] UnionMgr::CreateUnion...OnJoinUnion failed....charid:%llu,szName:%s, newuid:%u ", charId, szUnionName, newUid);
		return nullptr;
	}
	
	m_mapUnionByName[szUnionName] = pNewUnion;
	m_vecUnionId.push_back(newUid);

	LogInfoFmtPrint("UnionMgr::CreateUnion...newUid:%u,charId:%lu,szUnionName:%s,icondId:%u,homescene:%u ", newUid, charId, szUnionName, icondId,pNewUnion->UnionSceneId());

	//创建完成之后， 创建工会驻地场景
	CreateUnionScene(newUid,pNewUnion->Level());

	//创建工会，通知工会商城
	g_GetMallMgr()->RefreshGuildMall(pNewUnion->UnionId(), (uint32_t)pNewUnion->BuildLev(EUnionBuildType_Shop));
	LostCityJoinUnion(charId);
	g_GetActivityMgr()->OnJoinUnion(charId, pNewUnion->UnionId());

	//创建工会世界广播
	BroadCastCreateUnion(pNewUnion->UnionId(),pNewUnion->Name(),pNewUnion->LeaderId());


	//创建公会后，即时通知排行版刷新下公会排名
	g_GetRankingListMgr()->GetClanRankignList();


	return pNewUnion;
}


//能否创建工会
int32_t UnionMgr::CanCreate(CharIDType charId, int32_t iconId, string &strName, string &strNotice)
{
	ActiveCharacter *pCharOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pCharOnline)
	{
		return RET_PLAYER_NOT_ONLINE;
	}
	OfflineCharacterData *pCharOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pCharOffline)
	{
		return RET_FAIL;
	}
	if (pCharOffline->GetLevel() < UNION_OPEN_LEVEL)
	{
		//等级不足
		return RET_LEVEL_LACK;
	}

	if (GetCharUnionId(charId) > 0)
	{
		//已经加入工会
		return RET_UNION_ALREADY_JOIN;
	}
	if (nullptr != GetUnionByName(strName.c_str()))
	{
		//工会名字已经存在
		return RET_UNION_NAME_ALREAY_EXISTS;
	}
	//这里判断图片ID是否存在

	//工会名字长度判断
	int32_t name_len = strName.length();
	if (name_len <= 0 || name_len >= UNION_MAX_NAME_LEN)
	{
		//工会名字长度不符合规范
		return RET_UNION_NAME_LEN_LIMIT;
	}
	//公告名字长度判断
	int32_t notice_len = strNotice.length();
	if (notice_len < 0 || notice_len >= UNION_MAX_NOTICE_LEN)
	{
		//公告长度不符合规范
		return RET_UNION_NOTICE_LEN_LIMIT;
	}
	int8_t campId = pCharOffline->GetCampID();
	if (ECamp_Type_Light != campId && ECamp_Type_Dark != campId)
	{
		return RET_CAMP_NOT_JOIN_CAMP;
	}

	UnionChar *pCharUnion = CharUnionData(charId);
	if (nullptr == pCharUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
	if (curTime - pCharUnion->LastQuit() <= UNION_JOIN_INTER_SEC)
	{
		return RET_UNION_LAST_QUIT_TIME_LIMIT;
	}

	return RET_SUCCESS;
}

//能否加入工会
int32_t UnionMgr::CanJoin(CharIDType charId, int32_t level, int32_t campId, CUnion *pJoin)
{
	if (nullptr == pJoin)
	{
		//工会不存在
		return RET_UNION_NOT_EXISTS;
	}
	if (campId != pJoin->CampId())
	{
		//不是同一个阵营
		return RET_UNION_NOT_SAME_CAMP;
	}
	if (pJoin->IsMember(charId))
	{
		//已经加入工会
		return RET_UNION_ALREADY_JOIN;
	}
	if (level < pJoin->LevLimit() || level < UNION_OPEN_LEVEL)
	{
		//等级不足
		return RET_LEVEL_LACK;
	}
	if (pJoin->IsApply(charId))
	{
		return RET_UNION_ALREDAY_APPLY;
	}
	if (pJoin->IsFull())
	{
		//人数已满
		return RET_UNION_MEMBER_COUNT_LIMIT;
	}
	UnionChar *pCharUnion = CharUnionData(charId);
	if (nullptr == pCharUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
	if (curTime - pCharUnion->LastQuit() <= UNION_JOIN_INTER_SEC)
	{
		return RET_UNION_LAST_QUIT_TIME_LIMIT;
	}

	return RET_SUCCESS;
}

//能否加入工会
int32_t UnionMgr::CanJoin(CharIDType charId, uint32_t unionId)
{
	ActiveCharacter *pCharOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pCharOnline)
	{
		return RET_PLAYER_NOT_ONLINE;
	}
	OfflineCharacterData *pCharOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pCharOffline)
	{
		return RET_FAIL;
	}
	CUnion *pUnion = GetUnion(unionId);
	return CanJoin(charId, pCharOffline->GetLevel(), pCharOffline->GetCampID(), pUnion);
}
//能否加入工会
int32_t UnionMgr::CanJoin(CharIDType charId, SET_UINT32 &setUnionId, SET_UINT32 &setApplyUnion, uint32_t &joinId)
{
	ActiveCharacter *pCharOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pCharOnline)
	{
		return RET_PLAYER_NOT_ONLINE;
	}
	OfflineCharacterData *pCharOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pCharOffline)
	{
		return RET_FAIL;
	}
	if (GetCharUnionId(charId) > 0)
	{
		//已经加入工会
		return RET_UNION_ALREADY_JOIN;
	}
	int32_t applySize = (int32_t)setUnionId.size();
	if (applySize <= 0)
	{
		return RET_FAIL;
	}
	int32_t ret = RET_FAIL;
	if (1 == applySize)  //单个申请
	{
		uint32_t unionId = (*setUnionId.begin());
		CUnion *pJoin = GetUnion(unionId);
		ret = CanJoin(charId, pCharOffline->GetLevel(), pCharOffline->GetCampID(), pJoin);
		if (RET_SUCCESS == ret)
		{
			if (pJoin->IsAllowJoin())
			{
				joinId = unionId;
				setApplyUnion.clear();
			}
			else
			{
				setApplyUnion.insert(unionId);
			}
		}
		//
		return ret;
	}

	//批量申请
	int32_t retFlag = RET_SUCCESS;
	SET_UINT32::iterator iter = setUnionId.begin();
	while (iter != setUnionId.end())
	{
		uint32_t unionId = (*iter);
		CUnion *pJoin = GetUnion(unionId);
		ret = CanJoin(charId, pCharOffline->GetLevel(), pCharOffline->GetCampID(), pJoin);
		if (RET_SUCCESS == ret)
		{
			if (pJoin->IsAllowJoin())
			{
				joinId = unionId;
				setApplyUnion.clear();
				break;
			}
			else
			{
				setApplyUnion.insert(unionId);
			}
		}
		else if (RET_SUCCESS == retFlag)
		{
			retFlag = ret; //记录第一个出错的错误码
		}

		++iter;
	}
	//如果批量申请中，没有一个工会满足申请条件的话，返回第一个出错的错误码,
	if (joinId <= 0 && setApplyUnion.size() <= 0)
	{
		return retFlag;
	}
	//只要有一个工会满足加入条件，就返回成功
	return RET_SUCCESS;
}
//申请工会
CUnion *UnionMgr::ApplyUion(CharIDType charId, uint32_t unionId)
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	if (pUnion->IsApplyFull()) //申请已满,先删除一个申请
	{
		CharIDType delApplyCharId = 0;
		uint8_t delIdx = pUnion->CanDelApplyIdx(delApplyCharId);
		if (delIdx > 0)
		{
			pUnion->DelApply(delIdx);
			DelCharApply(delApplyCharId, unionId);
		}
		else
		{
			LogErrFmtPrint("[center] UnionMgr::ApplyUion.....CanDelApplyIdx return false....charid:%llu, unionid:%u, delIdx:%d ", charId, unionId, delIdx);
			return nullptr;
		}
	}
	if (!pUnion->AddApply(charId))
	{
		return nullptr;
	}
	//
	AddCharApply(charId, unionId);

	//通知申请列表更新
	NotifyApplyLstUpdate(unionId);

	return pUnion;
}
//加入工会
CUnion *UnionMgr::JoinUion(CharIDType charId, uint32_t unionId)
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	if (!pUnion->IsAllowJoin())
	{
		return nullptr;
	}
	//获取玩家所有的申请列表
	SET_UINT32 setApplyUnion;
	setApplyUnion.clear();
	SET_UINT32 *pCharApply = GetCharApply(charId);
	if (nullptr != pCharApply)
	{
		setApplyUnion = *pCharApply;
	}
	if (!OnJoinUnion(pUnion, charId, EUnionDutyType_Common))
	{
		return nullptr;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr != pOffline)
	{
		SET_UINT64 setMember;
		setMember.clear();
		pUnion->AllMember(setMember);
		BroadCastJoinAndQuit(setMember, pOffline->GetCharID(), 1);
	}
	SET_UINT32::iterator iterApply = setApplyUnion.begin();
	for (; iterApply != setApplyUnion.end(); ++iterApply)
	{
		//加入工会，会清空该玩家在其他公会的申请，需要通知其他公会申请列表有变化
		NotifyApplyLstUpdate((*iterApply));
	}	

	return pUnion;
}


//加入
bool UnionMgr::OnJoinUnion(CUnion *pUnion, CharIDType charId,int8_t duty,uint8_t idx /*= 0*/)
{
	if (nullptr == pUnion)
	{
		return false;
	}
	uint32_t unionId = pUnion->UnionId();
	//添加成员
	pUnion->AddMember(charId, duty);
	//删除申请
	DelCharApply(charId, unionId);
	if (idx > 0)
	{
		pUnion->DelApply(idx);
	}	
	//这里需要删除玩家之前申请过的所有工会
	ClearCharApply(charId);
	//添加玩家工会ID
	AddCharUnionId(charId, unionId);
	//加入工会，清空历史贡献
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr != pOffline)
	{
		pOffline->SetHistoryContri(0);
		AddCharOfflineSave(charId);
	}

	//同步工会信息
	SyncUnionInfo(charId);
	//
	UpdateCharUnionInfo(charId);

	g_GetActivityMgr()->OnJoinUnion(charId, unionId);
	g_GetEscortMgr()->OnJoinUnion(charId, unionId);
	g_GetMallMgr()->RefreshGuildMall(pUnion->UnionId(), (uint32_t)pUnion->BuildLev(EUnionBuildType_Shop));
	LostCityJoinUnion(charId);


	if (pOffline)
	{

		RankingListClanContribute stNode;
		stNode.set_clanname(pUnion->Name());
		stNode.set_username(pOffline->GetCharName());
		stNode.set_contributevalue(0);
		stNode.set_camp(pUnion->CampId());
		g_GetRankingListMgr()->AddClan(stNode);
	}


	return true;
}

//能否设置加入条件
int32_t UnionMgr::CanSetCondition(CharIDType charId, int32_t levLimit, int8_t joinType)
{
	ActiveCharacter *pCharOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pCharOnline)
	{
		return RET_PLAYER_NOT_ONLINE;
	}
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		//没有加入工会
		return RET_UNION_NOT_JOIN;
	}
	if (levLimit < 0 || !ValidJoinType(joinType))
	{
		return RET_UNION_SET_PARAM_ERROR;
	}
	int8_t duty = pUnion->MemberDuty(charId);
	const GuildPositionCfgInfo *pPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(duty);
	if (nullptr == pPosCfg || !pPosCfg->joinCondition)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}

	return RET_SUCCESS;
}

//设置加入条件
CUnion *UnionMgr::SetCondition(CharIDType charId, int32_t levLimit, int8_t joinType)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		//没有加入工会
		return nullptr;
	}
	pUnion->SetCondition(levLimit, joinType);
	return pUnion;
}

//能否退出工会
int32_t UnionMgr::CanQuit(CharIDType charId)
{
	ActiveCharacter *pCharOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pCharOnline)
	{
		return RET_PLAYER_NOT_ONLINE;
	}
	OfflineCharacterData *pCharOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pCharOffline)
	{
		return RET_FAIL;
	}
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		//没有加入工会
		return RET_UNION_NOT_JOIN;
	}
	if (!pUnion->IsMember(charId))
	{
		//没有加入工会
		return RET_UNION_NOT_JOIN;
	}
	if (pUnion->IsMemberDuty(charId,EUnionDutyType_Leader)) //会长退出
	{
		return RET_UNION_LEADER_CAN_NOT_EXIT;
	}

	return RET_SUCCESS;
}

//退出工会
CUnion *UnionMgr::QuitUnion(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		//没有加入工会
		return nullptr;
	}
	if (!pUnion->IsMember(charId))
	{
		return nullptr;
	}
	if (OnQuit(charId, pUnion, true))
	{
		//退出工会，广播
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
		if (nullptr != pOffline)
		{
			SET_UINT64 setMember;
			setMember.clear();
			pUnion->AllMember(setMember);
			BroadCastJoinAndQuit(setMember, pOffline->GetCharID(),0);
		}
	}

	return pUnion;
}

bool UnionMgr::OnQuit(CharIDType charId, CUnion *pUnion, bool isActive /*= false*/)
{
	if (nullptr == pUnion)
	{
		return false;
	}
	uint32_t unionId = pUnion->UnionId();
	UnionChar *pChar = CharUnionData(charId);
	if (nullptr != pChar)
	{
		pChar->Quit(isActive);
	}
	//删除成员
	pUnion->DelMember(charId);
	//退出工会，如果有政变的话，政变失败
	if (charId == pUnion->CoupCharId())
	{
		pUnion->CoupFinish();
	}
	//
	DelCharUnionId(charId);	
	//同步逻辑服玩家工会信息
	UpdateCharUnionInfo(charId);
	//同步客户端玩家工会信息
	SyncUnionInfo(charId);
	//退出工会 积分排名处理
	CloudScoreQuit(charId);

	//通知 所有工会相关的场景 把玩家踢出
	MAP_INT8_UINT32 mapAllScene;
	pUnion->AllScene(mapAllScene);
	MAP_INT8_UINT32::iterator iterScene = mapAllScene.begin();
	for (; iterScene != mapAllScene.end(); ++iterScene)
	{
		uint32_t sceneId = iterScene->second;
		uint32_t logicId = g_GetCenterDuplicateMgr()->dupSceneLogic(sceneId);
		NotifyLogicKick(charId, sceneId, logicId);
	}

	g_GetActivityMgr()->OnQuitUnion(charId, unionId);
	g_GetEscortMgr()->OnQuitUnion(charId, unionId);


	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (pOffline)
	{
		g_GetRankingListMgr()->LeaveClan(pOffline->GetCharName());
	}

	return true;
}

//设置工会列表页信息
void UnionMgr::SetUnionPageProto(UnionListPageProto *protoUnionPageList, int32_t pageIndex, CharIDType charId /*= 0*/)
{
	SetPageListProto(protoUnionPageList, pageIndex, m_vecUnionId, charId);
}

//查询工会
void UnionMgr::QueryUnion(string &strName, uint32_t pageIndex, UnionListPageProto *protoPageList, CharIDType charId/* = 0*/)
{
	//查找工会名字中含有strName 字符串的工会
	VEC_UINT32 vecQueryUnion;
	vecQueryUnion.clear();
	UnionMapByName::iterator iter = m_mapUnionByName.begin();
	for (; iter != m_mapUnionByName.end(); ++iter)
	{
		if (iter->first.find(strName) != string::npos)
		{
			CUnion *pUnion = iter->second;
			vecQueryUnion.push_back(pUnion->UnionId());
		}
	}
	//
	SetPageListProto(protoPageList, (int32_t)pageIndex, vecQueryUnion, charId);
}

//能否获取申请列表
int32_t UnionMgr::CanGetApplyList(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		//没有加入工会
		return RET_UNION_NOT_JOIN;
	}
	ActiveCharacter *pCharOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pCharOnline)
	{
		return RET_PLAYER_NOT_ONLINE;
	}
	OfflineCharacterData *pCharOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pCharOffline)
	{
		return RET_FAIL;
	}
	int8_t duty = pUnion->MemberDuty(charId);
	const GuildPositionCfgInfo *pGuildPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(duty);
	if (nullptr == pGuildPosCfg || !pGuildPosCfg->admitNewcomer)
	{
		//没有权限
		return RET_UNION_HAS_NO_PERMISSION;
	}	

	return RET_SUCCESS;
}

//能否获取工会大厅信息
int32_t UnionMgr::CanGetHall(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	return RET_SUCCESS;
}

//能否清空申请
int32_t UnionMgr::CanClearApply(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		//没有加入工会
		return RET_UNION_NOT_JOIN;
	}
	ActiveCharacter *pCharOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pCharOnline)
	{
		return RET_PLAYER_NOT_ONLINE;
	}
	OfflineCharacterData *pCharOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pCharOffline)
	{
		return RET_FAIL;
	}
	int8_t duty = pUnion->MemberDuty(charId);
	const GuildPositionCfgInfo *pGuildPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(duty);
	if (nullptr == pGuildPosCfg || !pGuildPosCfg->admitNewcomer)
	{
		//没有权限
		return RET_UNION_HAS_NO_PERMISSION;
	}

	return RET_SUCCESS;
}

//清空申请列表
CUnion *UnionMgr::ClearApply(CharIDType charId, SET_INT32 &setIndex)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		//没有加入工会
		return nullptr;
	}
	SET_INT32::iterator iter = setIndex.begin();
	while (iter != setIndex.end())
	{
		uint8_t idx = (*iter);
		CharIDType delCharId = pUnion->GetApplyCharByIdx(idx);
		if (!pUnion->DelApply(idx))
		{
			iter = setIndex.erase(iter);
			continue;
		}
		//
		DelCharApply(delCharId, pUnion->UnionId());

		++iter;
	}

	//通知申请列表更新
	NotifyApplyLstUpdate(pUnion->UnionId());

	return pUnion;
}

//能否通过申请
int32_t UnionMgr::CanPassApply(CharIDType charId, int32_t idx,CharIDType &joinCharId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	CharIDType applyCharId = pUnion->GetApplyCharByIdx(idx);
	if (applyCharId <= 0)
	{
		return RET_UNION_APPLY_NOT_EXISTS;
	}
	CUnion *pOtherUnion = GetCharUnion(applyCharId);
	if (nullptr != pOtherUnion)
	{
		if (pOtherUnion->UnionId() == pUnion->UnionId())
		{
			return RET_UNION_OTHER_ALREDY_JOIN;
		}
		else
		{
			return RET_UNION_OTHER_ALREDY_JOIN_OTHER;
		}
	}
	else if (pUnion->IsMember(applyCharId))
	{
		return RET_UNION_OTHER_ALREDY_JOIN;
	}
	else if (pUnion->IsFull())
	{
		return RET_UNION_MEMBER_COUNT_LIMIT;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(applyCharId);
	if (nullptr == pOffline)
	{
		return RET_FAIL;
	}
	//验证对方能否加入工会
	if (pOffline->GetLevel() < pUnion->LevLimit())
	{
		return RET_LEVEL_LACK;
	}
	if (pOffline->GetCampID() != pUnion->CampId())
	{
		return RET_UNION_NOT_SAME_CAMP;
	}
	//
	joinCharId = applyCharId;

	return RET_SUCCESS;
}
//能否通过申请
int32_t UnionMgr::CanPassApply(CharIDType charId, CUnion *pUnion, int32_t idx)
{
	if (nullptr == pUnion)
	{
		return RET_FAIL;
	}
	CharIDType applyCharId = pUnion->GetApplyCharByIdx(idx);
	if (applyCharId <= 0)
	{
		return RET_UNION_APPLY_NOT_EXISTS;
	}
	CUnion *pOtherUnion = GetCharUnion(applyCharId);
	if (nullptr != pOtherUnion)
	{
		if (pOtherUnion->UnionId() == pUnion->UnionId())
		{
			return RET_UNION_OTHER_ALREDY_JOIN;
		}
		else
		{
			return RET_UNION_OTHER_ALREDY_JOIN_OTHER;
		}
	}
	else if (pUnion->IsMember(applyCharId))
	{
		return RET_UNION_OTHER_ALREDY_JOIN;
	}
	else if (pUnion->IsFull())
	{
		return RET_UNION_MEMBER_COUNT_LIMIT;
	}
	else if (charId == applyCharId)
	{
		return RET_UNION_OTHER_ALREDY_JOIN;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(applyCharId);
	if (nullptr == pOffline)
	{
		return RET_FAIL;
	}
	//验证对方能否加入工会
	if (pOffline->GetLevel() < pUnion->LevLimit())
	{
		return RET_LEVEL_LACK;
	}
	if (pOffline->GetCampID() != pUnion->CampId())
	{
		return RET_UNION_NOT_SAME_CAMP;
	}
	return RET_SUCCESS;
}
//能否通过申请
int32_t UnionMgr::CanPassApply(CharIDType charId, SET_INT32 &setApplyIdx, SET_INT32 &setDelApply, SET_INT32 &setPassApply)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	int8_t duty = pUnion->MemberDuty(charId);
	const GuildPositionCfgInfo *pPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(duty);
	if (nullptr == pPosCfg || !pPosCfg->admitNewcomer)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}
	SET_INT32::iterator iter = setApplyIdx.begin();
	while (iter != setApplyIdx.end())
	{
		int32_t idx = (*iter);
		if (RET_SUCCESS != CanPassApply(charId, pUnion, idx))
		{
			setDelApply.insert(idx);
		}
		else
		{
			setPassApply.insert(idx);
		}

		++iter;
	}
	return RET_SUCCESS;
}

//通过申请
CUnion *UnionMgr::PassApply(CharIDType charId, SET_INT32 &setDelApplyIdx, SET_INT32 &setPassApplyIdx)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		return nullptr;
	}
	uint32_t unionId = pUnion->UnionId();
	SET_INT32::iterator iter = setPassApplyIdx.begin();
	while (iter != setPassApplyIdx.end())
	{
		int32_t idx = (*iter);
		CharIDType applyCharId = pUnion->GetApplyCharByIdx(idx);
		if (applyCharId <= 0)
		{
			setDelApplyIdx.insert(idx);
			iter = setPassApplyIdx.erase(iter);
			continue;
		}
		if (pUnion->IsFull()) //这里需要判断是否已经满员了
		{
			setDelApplyIdx.insert(idx);
			iter = setPassApplyIdx.erase(iter);
			continue;
		}
		if (!OnJoinUnion(pUnion, applyCharId, EUnionDutyType_Common, idx))
		{
			setDelApplyIdx.insert(idx);
			iter = setPassApplyIdx.erase(iter);
			continue;
		}

		++iter;
	}

	SET_INT32::iterator iterDel = setDelApplyIdx.begin();
	for (; iterDel != setDelApplyIdx.end(); ++iterDel)
	{
		int32_t idx = (*iterDel);
		CharIDType applyCharId = pUnion->GetApplyCharByIdx(idx);
		pUnion->DelApply(idx);
		if (applyCharId > 0)
		{
			DelCharApply(applyCharId, unionId);
		}
	}

	//通知申请列表更新
	NotifyApplyLstUpdate(unionId);

	return pUnion;
}


//能否获取成员列表
int32_t UnionMgr::CanGetMemberList(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	return RET_SUCCESS;
}

//能否转让工会
int32_t UnionMgr::CanTrans(CharIDType charId, CharIDType transCharId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	if (charId == transCharId)
	{
		return RET_UNION_CAN_NOT_TRANS_SELF;
	}
	ActiveCharacter *pCharOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pCharOnline)
	{
		return RET_PLAYER_NOT_ONLINE;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		return RET_FAIL;
	}
	OfflineCharacterData *pTransOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(transCharId);
	if (nullptr == pTransOffline)
	{
		return RET_FAIL;
	}
	if (!pUnion->IsMember(transCharId))
	{
		return RET_UNION_OTHER_NOT_JOIN;
	}
	if (!pUnion->IsMemberDuty(charId,EUnionDutyType_Leader))
	{
		return RET_UNION_NOT_LEADER;
	}
	if (!pUnion->IsMemberDuty(transCharId,EUnionDutyType_Vice))
	{
		return RET_UNION_CAN_NOT_TRANS_NO_VICE;
	}
	
	return RET_SUCCESS;
}

//转让工会
CUnion* UnionMgr::Trans(CharIDType charId, CharIDType transCharId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		return nullptr;
	}
	OfflineCharacterData *pTransOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(transCharId);
	if (nullptr == pTransOffline)
	{
		return nullptr;
	}

	SET_UINT64 setMember;
	setMember.clear();
	pUnion->AllMember(setMember);
	CharIDType coupCharId = pUnion->CoupCharId();
	if (coupCharId > 0)	//如果有政变，政变失败
	{
		pUnion->CoupFinish();

		OfflineCharacterData *pCoupOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(coupCharId);
		if (nullptr != pCoupOffline)
		{
			//政变失败
			BroadCastCoup(setMember, pCoupOffline->GetCharName(),2);
		}
	}

	pUnion->ModifyMemberDuty(charId,pOffline->GetCharName(), EUnionDutyType_Common);
	pUnion->ModifyMemberDuty(transCharId, pTransOffline->GetCharName(), EUnionDutyType_Leader);

	SyncUnionInfo(transCharId);
	UpdateCharUnionInfo(transCharId);
	SyncUnionInfo(charId);
	UpdateCharUnionInfo(charId);
	//转让广播	
	BroadCastLeaderTrans(setMember, pTransOffline->GetCharName());
	//通知逻辑服会长外观
	NotifyLeaderFacadeUpdate(pUnion->UnionId());

	return pUnion;
}

//能否解散工会
int32_t UnionMgr::CanDismiss(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	if (!pUnion->IsMemberDuty(charId, EUnionDutyType_Leader))
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}
	if (mLostCity[ECamp_Type_Light].unionId == pUnion->UnionId()
		|| mLostCity[ECamp_Type_Dark].unionId == pUnion->UnionId()
		)
	{
		return RET_UNION_IN_LOST_CITY_ACT;
	}
	return RET_SUCCESS;
}


//解散工会
int32_t UnionMgr::Dismiss(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	uint32_t unionId = pUnion->UnionId();
	//通知所有人，工会解散
	NotifyDismiss(unionId);
	//
	SET_UINT64 setMember;
	setMember.clear();
	pUnion->AllMember(setMember);
	//所有成员退出
	bool isActive = false;
	SET_UINT64::iterator iter = setMember.begin();
	for (; iter != setMember.end(); ++iter)
	{
		CharIDType cid = (*iter);
		isActive = false;
		if (charId == cid) //如果是会长,当做主动离开
		{
			isActive = true;
		}
		OnQuit(cid, pUnion, isActive);
	}
	//删除工会
	DelUnionDBData(unionId);
	//通知 工会所有场景 所在的 逻辑服工会销毁
	MAP_INT8_UINT32 mapAllScene;
	pUnion->AllScene(mapAllScene);
	MAP_INT8_UINT32::iterator iterScene = mapAllScene.begin();
	for (; iterScene != mapAllScene.end(); ++iterScene)
	{
		uint32_t sceneId = iterScene->second;
		uint32_t logicId = g_GetCenterDuplicateMgr()->dupSceneLogic(sceneId);
		NotifyLogicDismiss(unionId, sceneId, logicId);
		//通知副本，场景结束
		g_GetCenterDuplicateMgr()->unionDismiss(sceneId);
	}

	//回收工会
	RecycleUnion(pUnion);
	//解散工会积分排名处理
	CloudScoreDismiss(unionId);

	//工会解散，通知工会商城
	g_GetEscortMgr()->OnDisbUnion(unionId);
	g_GetRankingListMgr()->GetClanRankignList();

	return RET_SUCCESS;
}

//能否任命职务
int32_t UnionMgr::CanAppoint(CharIDType charId, CharIDType appointCharId, int8_t duty,int8_t &oldDuty)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	if (!ValidDuty(duty))
	{
		return RET_UNION_INVALID_DUTY;
	}
	if (charId == appointCharId)
	{
		return RET_FAIL;
	}
	if (!pUnion->IsMember(charId))
	{
		return RET_UNION_NOT_JOIN;
	}
	if (!pUnion->IsMember(appointCharId))
	{
		return RET_UNION_OTHER_NOT_JOIN;
	}
	if (duty == pUnion->MemberDuty(appointCharId))
	{
		return RET_UNION_ALREDAY_SAME_DUTY;
	}
	const GuildConstantCfgInfo *pConstCfg = g_GetUnionCfgMgr()->GetUnionInitCfgInfo();
	if (nullptr == pConstCfg)
	{
		return RET_FAIL;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(appointCharId);
	if (nullptr == pOffline)
	{
		return RET_FAIL;
	}
	int8_t char_duty = pUnion->MemberDuty(charId);
	const GuildPositionCfgInfo *pPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(char_duty);
	if (nullptr == pPosCfg)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}
	else if (	(EUnionDutyType_Vice == duty && pPosCfg->appointAndRemoveVP)
				|| (EUnionDutyType_Elder == duty && pPosCfg->appointAndRemoveElder)
				|| (EUnionDutyType_Elite == duty && pPosCfg->appointAndRemoveElite)
		)
	{
		int32_t level = pUnion->BuildLev(EUnionBuildType_Hall);
		if (level > 0 && level <= (int32_t)pConstCfg->vecGuildConstantGuildLevelCfg.size())
		{
			const GuildConstantGuildLevelCfgInfo &infoCfg = pConstCfg->vecGuildConstantGuildLevelCfg.at(level - 1);
			if (
				(EUnionDutyType_Vice == duty && (pUnion->MemberCount(EUnionDutyType_Vice) < infoCfg.VP) )
				 || (EUnionDutyType_Elite == duty && (pUnion->MemberCount(EUnionDutyType_Elite) < infoCfg.Elite))
				 || (EUnionDutyType_Elder == duty && (pUnion->MemberCount(EUnionDutyType_Elder) < infoCfg.Elder))
				)
			{
				oldDuty = pUnion->MemberDuty(appointCharId);
				return RET_SUCCESS;
			}
		}
		return RET_UNION_DUTY_COUNT_LIMIT;
	}

	return RET_UNION_HAS_NO_PERMISSION;
}
//任命职务
CUnion *UnionMgr::Appoint(CharIDType charId, CharIDType appointCharId, int8_t duty)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(appointCharId);
	if (nullptr == pOffline)
	{
		return nullptr;
	}
	pUnion->ModifyMemberDuty(appointCharId, pOffline->GetCharName(), duty);
	//
	SyncUnionInfo(appointCharId);
	UpdateCharUnionInfo(appointCharId);
	//
	return pUnion;
}
//能否解除职务
int32_t UnionMgr::CanRelieve(CharIDType charId, CharIDType relieveCharId,int8_t &oldDuty)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	if (charId == relieveCharId)
	{
		return RET_FAIL;
	}
	if (!pUnion->IsMember(charId))
	{
		return RET_UNION_NOT_JOIN;
	}
	if (!pUnion->IsMember(relieveCharId))
	{
		return RET_UNION_OTHER_NOT_JOIN;
	}
	int8_t relieveDuty = pUnion->MemberDuty(relieveCharId);
	if (EUnionDutyType_Common == relieveDuty)
	{
		return RET_UNION_ALREADY_COMMOM_MEMBER;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(relieveCharId);
	if (nullptr == pOffline)
	{
		return RET_FAIL;
	}
	
	int8_t char_duty = pUnion->MemberDuty(charId);
	const GuildPositionCfgInfo *pPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(char_duty);
	if (nullptr == pPosCfg)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}
	else if ((EUnionDutyType_Vice == relieveDuty && pPosCfg->appointAndRemoveVP)
		|| (EUnionDutyType_Elder == relieveDuty && pPosCfg->appointAndRemoveElder)
		|| (EUnionDutyType_Elite == relieveDuty && pPosCfg->appointAndRemoveElite)
		)
	{
		oldDuty = relieveDuty;
		return RET_SUCCESS;
	}

	return RET_UNION_HAS_NO_PERMISSION;
}
//解除职务
CUnion *UnionMgr::Relieve(CharIDType charId, CharIDType relieveCharId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(relieveCharId);
	if (nullptr == pOffline)
	{
		return nullptr;
	}
	pUnion->ModifyMemberDuty(relieveCharId, pOffline->GetCharName(), EUnionDutyType_Common);

	SyncUnionInfo(relieveCharId);
	UpdateCharUnionInfo(relieveCharId);
	return pUnion;
}

//能否踢出
int32_t UnionMgr::CanKick(CharIDType charId, CharIDType kickCharId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	if (!pUnion->IsMember(kickCharId))
	{
		return RET_UNION_OTHER_NOT_JOIN;
	}
	if (charId == kickCharId)
	{
		return RET_FAIL;
	}
	if (pUnion->CoupCharId() > 0)//政变期间不能提出操作
	{
		return RET_UNION_CAN_NOT_KICK_IN_COUP;
	}
	int8_t charDuty = pUnion->MemberDuty(charId);
	int8_t kickDuty = pUnion->MemberDuty(kickCharId);
	const GuildPositionCfgInfo *pPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(charDuty);
	if (nullptr == pPosCfg)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}
	if (  (EUnionDutyType_Common == kickDuty && pPosCfg->expelMass)
		|| (EUnionDutyType_Elite == kickDuty && pPosCfg->expelElite)
		|| (EUnionDutyType_Elder == kickDuty && pPosCfg->expelElder)
		|| (EUnionDutyType_Vice == kickDuty && pPosCfg->expelVP)
		
		)
	{
		return RET_SUCCESS;
	}
	
	return RET_UNION_HAS_NO_PERMISSION;
}
//踢出
CUnion *UnionMgr::Kick(CharIDType charId, CharIDType kickCharId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	if (OnQuit(kickCharId, pUnion))
	{
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
		OfflineCharacterData *pKickOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(kickCharId);
		if (nullptr != pOffline && nullptr != pKickOffline)
		{
			SET_UINT64 setMember;
			setMember.clear();
			pUnion->AllMember(setMember);
			BroadCastKickOut(setMember, pUnion->MemberDuty(charId), pOffline->GetCharName(), pKickOffline->GetCharName());
		}		
	}

	return pUnion;
}

//能否编辑公告
int32_t UnionMgr::CanEditNotice(CharIDType charId, string &strNotce)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	if (!pUnion->IsMember(charId))
	{
		return RET_UNION_NOT_JOIN;
	}
	int32_t len = strNotce.length();
	if (len >= UNION_MAX_NOTICE_LEN -1)
	{
		return RET_UNION_NOTICE_LEN_LIMIT;
	}
	uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
	uint64_t lastNotice = pUnion->LastNotice();
	if (curTime - lastNotice < UNION_NOTICE_INTER_SEC)
	{
		return RET_UNION_NOTICE_INTER_SEC_LIMIT;
	}
	int8_t duty = pUnion->MemberDuty(charId);
	const GuildPositionCfgInfo *pPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(duty);
	if (nullptr == pPosCfg || !pPosCfg->announcementEditing)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}

	return RET_SUCCESS;
}

//编辑公告
CUnion *UnionMgr::EditNotice(CharIDType charId, string &strNotce)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	pUnion->EditNotice(strNotce);
	//
	BroadCastEditNotice(charId,strNotce);

	return pUnion;
}

//能否升级工会
int32_t UnionMgr::CanUpgrade(CharIDType charId,int8_t buildType)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	if (!pUnion->IsMember(charId))
	{
		return RET_UNION_NOT_JOIN;
	}
	int8_t duty = pUnion->MemberDuty(charId);
	const GuildPositionCfgInfo *pPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(duty);
	if (nullptr == pPosCfg || !pPosCfg->buildingUpgrade)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}
	int8_t buildLev = pUnion->BuildLev(buildType);
	if (buildLev < 0)
	{
		return RET_FAIL;
	}
	const GuildUpgradeConditionCfgInfo *pUpgradeCfg = g_GetUnionCfgMgr()->GetUnionUpgradeCfgInfo(buildType, (int32_t)(buildLev + 1));
	if (nullptr == pUpgradeCfg)
	{
		return RET_UNION_BUILD_LEVEL_LIMIT;
	}
	const GuildBuildingCfgInfo *pBuildCfg = g_GetUnionCfgMgr()->GetBuildingCfg(buildType);
	if (nullptr == pBuildCfg)
	{
		return RET_UNION_BUILD_LEVEL_LIMIT;
	}
	int32_t buildSize = pBuildCfg->vecGuildBuildingUpgradeCfg.size();
	if (buildSize < buildLev)
	{
		return RET_UNION_BUILD_LEVEL_LIMIT;
	}
	int32_t costNeed = pBuildCfg->vecGuildBuildingUpgradeCfg.at(buildLev - 1).Spend; // vecGuildBuildingUpgradeCfg 是从 2级到5级的配置，默认工会是1级
	if (pUnion->Money() < (uint64_t)costNeed)
	{
		return RET_UNION_MONEY_LACK;
	}
	
	const MAP_INT8_INT8 *pUpgradeLevNeedCfg = g_GetUnionCfgMgr()->GetUnionUpgradeNeedCfg(buildType, (int32_t)(buildLev + 1));
	if (nullptr == pUpgradeLevNeedCfg)
	{
		return RET_UNION_BUILD_LEVEL_LIMIT;
	}
	if (pUnion->Money() < (uint64_t)pUpgradeCfg->guildMoneyCondition)
	{
		return RET_UNION_MONEY_LACK;
	}
	MAP_INT8_INT8::const_iterator iter = pUpgradeLevNeedCfg->begin();
	for (; iter != pUpgradeLevNeedCfg->end(); ++iter)
	{
		int8_t buildTypeNeed = iter->first;
		if (buildType == buildTypeNeed)
		{
			continue;
		}
		if (pUnion->BuildLev(buildTypeNeed) < iter->second)
		{
			return RET_UNION_BUILD_LEV_NOT_ENOUGH;
		}
	}

	return RET_SUCCESS;
}
//升级工会
CUnion *UnionMgr::Upgrade(CharIDType charId,int8_t buildType)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	int8_t buildLev = pUnion->BuildLev(buildType);
	if (buildLev < 0)
	{
		return nullptr;
	}
	const GuildBuildingCfgInfo *pBuildCfg = g_GetUnionCfgMgr()->GetBuildingCfg(buildType);
	if (nullptr == pBuildCfg)
	{
		return nullptr;
	}
	int32_t buildSize = pBuildCfg->vecGuildBuildingUpgradeCfg.size();
	if (buildSize < buildLev)
	{
		return nullptr;
	}
	int32_t costNeed = pBuildCfg->vecGuildBuildingUpgradeCfg.at(buildLev - 1).Spend; // vecGuildBuildingUpgradeCfg 是从 2级到5级的配置，默认工会是1级
	pUnion->BuildUpgrade(buildType, costNeed);
	if (EUnionBuildType_Hall == buildType 
		|| EUnionBuildType_Office == buildType
		|| EUnionBuildType_Vault == buildType
		) //工会等级 事务所等级 金库等级 变化，需要同步到逻辑服
	{
		SET_UINT64 setMember;
		setMember.clear();
		pUnion->AllMember(setMember);
		SET_UINT64::iterator iter = setMember.begin();
		for (; iter != setMember.end(); ++iter)
		{
			UpdateCharUnionInfo((*iter));
		}
	}
	if (EUnionBuildType_Hall == buildType)
	{
		//通知逻辑服工会驻地，工会等级更新
		NotifyLogicUnionLevUpdate(pUnion->UnionId(), (int32_t)pUnion->Level(), pUnion->UnionSceneId());
		//
		g_GetCNotifyMgr()->OnUnionHallLev(pUnion->Name(), pUnion->BuildLev(buildType));
	}
	//通知其他成员
	NotifyMgr(pUnion->UnionId());
	//建筑升级广播
	SET_UINT64 setMember;
	setMember.clear();
	pUnion->AllMember(setMember);
	BroadCastBuildUpgrade(setMember, buildType, pUnion->BuildLev(buildType));

	return pUnion;
}

//能否回到工会
int32_t UnionMgr::CanReturn(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		return RET_NOT_ONLINE;
	}
	if (pOnline->GetSceneID() == pUnion->UnionSceneId())
	{
		return RET_UNION_ALREADY_IN_HOME;
	}
	int32_t ret = g_GetCenterDuplicateMgr()->canEnterUnionHomeDup(charId, pUnion->UnionSceneId());

	//这里添加其他限制判断



	return ret;
}
//回到工会
CUnion * UnionMgr::Return(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	SUnionSceneParam param;
	param.charId = charId;
	param.dupId = g_GetDuplicateCfgMgr()->GetUnionHomeDupId();
	param.sceneType = EUnionSceneType_Home;
	param.unionId = pUnion->UnionId();
	int32_t ret = g_GetCenterDuplicateMgr()->enterUnionSceneDup(param);
	if (RET_SUCCESS != ret)
	{
		return nullptr;
	}

	return pUnion;
}

//能否更改徽章
int32_t UnionMgr::CanChangeIcon(CharIDType charId, int32_t iconId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}

	int8_t char_duty = pUnion->MemberDuty(charId);
	const GuildPositionCfgInfo *pPosCfg = g_GetUnionCfgMgr()->GetUnionPosCfgInfo(char_duty);
	if (nullptr == pPosCfg || !pPosCfg->changeBadge)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}
	if (iconId == pUnion->IconId())
	{
		return RET_UNION_CAN_NOT_CHANGE_SAME_ICON;
	}
	const GuildConstantCfgInfo *pGuildConst = g_GetUnionCfgMgr()->GetUnionInitCfgInfo();
	if (nullptr == pGuildConst)
	{
		return RET_FAIL;
	}
	if (pUnion->Money() < (uint64_t)pGuildConst->changeBadgeSpend)
	{
		return RET_UNION_MONEY_LACK;
	}


	return RET_SUCCESS;
}
//更改徽章
CUnion *UnionMgr::ChangeIcon(CharIDType charId, int32_t iconId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	
	pUnion->ChangeIcon(iconId);

	//扣除工会资金
	const GuildConstantCfgInfo *pGuildConst = g_GetUnionCfgMgr()->GetUnionInitCfgInfo();
	if (nullptr != pGuildConst)
	{
		AddUnionMoney(charId, -pGuildConst->changeBadgeSpend);
	}

	SET_UINT64 setMember;
	setMember.clear();
	pUnion->AllMember(setMember);
	SET_UINT64::iterator iter = setMember.begin();
	for (; iter != setMember.end(); ++iter)
	{
		UpdateCharUnionInfo((*iter));
		SyncUnionInfo((*iter));
	}

	return pUnion;
	
}


//能否发起政变
int32_t UnionMgr::CanStartCoup(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	return pUnion->CanStartCoup(charId);
}
//发起政变
CUnion *UnionMgr::StartCoup(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	pUnion->StartCoup(charId);

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr != pOffline)
	{
		SET_UINT64 setMember;
		setMember.clear();
		pUnion->AllMember(setMember);
		BroadCastCoup(setMember, pOffline->GetCharName(), 0);
	}

	return pUnion;
}

//能否响应政变
int32_t UnionMgr::CanRspCoup(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	return pUnion->CanRspCoup(charId);
}
//响应政变
CUnion * UnionMgr::RspCoup(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	CharIDType leaderId = pUnion->LeaderId();
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(leaderId);
	if (nullptr == pOffline)
	{
		return nullptr;
	}
	CharIDType coupCharId = pUnion->CoupCharId();
	OfflineCharacterData *pCoupOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(coupCharId);
	if (nullptr == pCoupOffline)
	{
		return nullptr;
	}

	pUnion->RspCoup(charId);

	if (pUnion->IsCoupFinish())
	{	

		//完成响应，政变成功，修改政变成员的职位 为会长，会长职位修改为普通成员
		pUnion->ModifyMemberDuty(leaderId, pOffline->GetCharName(), EUnionDutyType_Common);
		pUnion->ModifyMemberDuty(coupCharId, pCoupOffline->GetCharName(), EUnionDutyType_Leader);
		//政变成功
		pUnion->CoupFinish();

		//
		SyncUnionInfo(leaderId);
		UpdateCharUnionInfo(leaderId);
		SyncUnionInfo(coupCharId);
		UpdateCharUnionInfo(coupCharId);

		//
		SET_UINT64 setMember;
		setMember.clear();
		pUnion->AllMember(setMember);
		BroadCastCoup(setMember, pCoupOffline->GetCharName(), 1);
	}

	return pUnion;
}

//能否获取工会积分榜
int32_t UnionMgr::CanGetUnionScoreRank(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	return RET_SUCCESS;
}
//获取工会积分信息
CUnion *UnionMgr::UnionScoreRank(CharIDType charId, UnionAllScoreRankProto &proto)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	SetUnionScoreRankProto(proto);
	return pUnion;
}
//能否获取玩家积分榜
int32_t UnionMgr::CanGetCharScoreRank(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	return RET_SUCCESS;
}
//获取玩家积分榜
CUnion *UnionMgr::CharScoreRank(CharIDType charId, UnionAllCharScoreRankProto &proto)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	SetCharScoreRankProto(proto);
	return pUnion;
}

//能否领取积分奖励
int32_t UnionMgr::CanFetchScoreReward(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	if (pUnion->IsFetchScore(charId))
	{
		return RET_UNION_ALREADY_FETCH_SCORE;
	}
	//活动期间，未通关不能领取
	uint32_t clouActId = g_GetDuplicateCfgMgr()->GetCloudActId();
	if (g_GetActivityMgr()->IsActivityRunning(clouActId))
	{
		if (!pUnion->IsCloudPass())
		{
			return RET_UNION_NOT_PASS_CLOUD;
		}
	}
	/*
	if (!pUnion->IsCloudPass())
	{
		return RET_UNION_NOT_PASS_CLOUD;
	}*/
	int32_t score = pUnion->MemCloudScore(charId);
	if (score <= 0)
	{
		return RET_UNION_CAN_NOT_FETCH_SCROE_REWARD;
	}
	uint64_t totalScore = pUnion->TotalScore();
	uint32_t boxId = GetCloudScoreBoxId(totalScore);
	const BoxDropCfgInfo *pBoxDropCfg = g_GetBoxDropCfgTable()->GetBoxDropCfgInfo(boxId);
	if (nullptr == pBoxDropCfg)
	{
		return RET_UNION_CHAR_SCORE_LIMIT;
	}
	return RET_SUCCESS;
}
//领取积分奖励
CUnion *UnionMgr::FetchScoreReward(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	uint64_t totalScore = pUnion->TotalScore();
	uint32_t boxId = GetCloudScoreBoxId(totalScore);
	const BoxDropCfgInfo *pBoxDropCfg = g_GetBoxDropCfgTable()->GetBoxDropCfgInfo(boxId);
	if (nullptr == pBoxDropCfg)
	{
		LogErrFmtPrint("[center] UnionMgr::FetchScoreReward....nullptr == pBoxDropCfg boxId:%u ", boxId);
		return nullptr;
	}
	bool maxLevBoxFlag = (boxId == g_GetUnionCfgMgr()->GetCloudMaxLevBoxId());
	//这里先设置已领取，再到逻辑服添加到背包，如果失败，逻辑服再通知设置未领取
	pUnion->MemFetchScore(charId);	
	//通知逻辑服领取宝箱奖励
	NotifyLogicFetchScore(charId, boxId, maxLevBoxFlag);

	return pUnion;
}
//领取积分奖励失败
void UnionMgr::FetchScoreRewardFailed(CharIDType charId)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr != pUnion)
	{
		pUnion->MemFetchScoreFaild(charId);
	}
}

//是否可以开始研究
int32_t UnionMgr::CanStartResearch(CharIDType charId, int8_t type)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	int8_t dupty = pUnion->MemberDuty(charId);
	if (dupty != EUnionDutyType_Leader && dupty != EUnionDutyType_Vice)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}
	return pUnion->CanStartResearch(type);
}
//开始研究
CUnion *UnionMgr::StartResearch(CharIDType charId, int8_t type)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	pUnion->StartResearch(type);
	return pUnion;
}
//是否可以暂停研究
int32_t UnionMgr::CanPauseResearch(CharIDType charId, int8_t type)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	int8_t dupty = pUnion->MemberDuty(charId);
	if (dupty != EUnionDutyType_Leader && dupty != EUnionDutyType_Vice)
	{
		return RET_UNION_HAS_NO_PERMISSION;
	}
	return pUnion->CanPauseResearch(type);
}
//暂停研究
CUnion *UnionMgr::PauseResearch(CharIDType charId, int8_t type)
{
	CUnion *pUnion = GetCharUnion(charId);
	if (nullptr == pUnion)
	{
		return nullptr;
	}
	pUnion->PauseResearch(type);
	return pUnion;
}

//能否邀请
int32_t UnionMgr::CanInvite(CharIDType cid, CharIDType inviteCid)
{
	//邀请这里只判断 阵营，玩家等级是否大于 工会系统开启等级，其他的能否加入工会的判断放到 玩家同意邀请那边判断
	CUnion *pUnion = GetCharUnion(cid);
	if (nullptr == pUnion)
	{
		return RET_UNION_NOT_JOIN;
	}
	if (GetCharUnionId(inviteCid) > 0)
	{
		return RET_UNION_OTHER_ALREDY_JOIN;
	}
	OfflineCharacterData *pInviteOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(inviteCid);
	if (nullptr == pInviteOffline)
	{
		return RET_CONFIG_ERROR;
	}
	if (pUnion->CampId() != pInviteOffline->GetCampID())
	{
		return RET_UNION_NOT_SAME_CAMP;
	}
	//判断开启等级 
	const ConstantConstantCfgInfo *pConstCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_UnionOpenLevel);
	if (nullptr == pConstCfg)
	{
		LogErrFmtPrint("[center] nullptr == pConstCfg...id:%d ", EArg_UnionOpenLevel);
		return RET_DATA_ERROR;
	}
	if (pInviteOffline->GetLevel() < pConstCfg->constantdata)
	{
		return RET_OTHER_LEVEL_LACK;
	}

	return RET_SUCCESS;
}
//邀请
bool UnionMgr::Invite(CharIDType cid, CharIDType inviteCid)
{
	CUnion *pUnion = GetCharUnion(cid);
	if (nullptr == pUnion)
	{
		return false;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(cid);
	if (nullptr == pOffline)
	{
		return false;
	}

	UnionNotifyInivteRsp rsp;
	UnionInviteProto *protoInvite = rsp.mutable_new_invite();
	protoInvite->set_invite_cid(cid);
	protoInvite->set_invite_name(pOffline->GetCharName());
	protoInvite->set_invite_prof(pOffline->GetProf());
	protoInvite->set_invite_sex(pOffline->GetSex());
	protoInvite->set_level(pOffline->GetLevel());
	protoInvite->set_fight(pOffline->GetFight());
	protoInvite->set_invite_union_name(pUnion->Name());
	protoInvite->set_invite_union_lev(pUnion->Level());
	protoInvite->set_invite_union_id(pUnion->UnionId());
	g_GetCenterService()->SendDataToClient(inviteCid, EMODULE_ID_UNION, CENTER_TO_CLIENT_UNION_NOTIFY_INVITE,&rsp);

	return true;
}
//通知工会，解散
void UnionMgr::NotifyDismiss(uint32_t unionId)
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr != pUnion)
	{
		Union_NotifyDismiss notify;
		pUnion->BroadUnionData(EMODULE_ID_UNION, CENTER_TO_CLIENT_NOTIFY_DISMISS, &notify);
	}
}

//通知管理信息
void UnionMgr::NotifyMgr(uint32_t unionId)
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr != pUnion)
	{
		Union_NotifyMgrRsp rsp;
		UnionMgrProto *proto = rsp.mutable_mgr();
		pUnion->SetUnionMgrProto(proto);
		pUnion->BroadUnionData(EMODULE_ID_UNION, CENTER_TO_CLIENT_UNION_NOTIFY_MGR, &rsp);
	}
}

//通知成员被踢出
void UnionMgr::NotifyBeKick( CharIDType charId)
{
	Union_NotifyBeKick notify;
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_UNION, CENTER_TO_CLIENT_NOTIFY_BE_KICK, &notify);
}

//通知逻辑服工会踢出成员
void UnionMgr::NotifyLogicKick(CharIDType charId, uint32_t sceneId, uint32_t logicId)
{
	CL_UnionKickMemRsp rsp;
	rsp.set_char_id(charId);
	rsp.set_scene_id(sceneId);
	if (!g_GetCenterService()->SendDataToLogic(logicId, EMODULE_ID_UNION, CENTER_TO_LOGIC_UNION_KICK_MEM, &rsp))
	{
		LogErrFmtPrint("[center] UnionMgr::NotifyLogicKick...SendDataToLogic failed....charid:%llu, sceneid:%u, logicID:%u ", charId, sceneId, logicId);
	}
}

//通知逻辑服领取积分奖励
void UnionMgr::NotifyLogicFetchScore(CharIDType charId, uint32_t boxId, bool maxLevBoxFlag)
{
	CL_UnionFetchScoreRsp rsp;
	rsp.set_char_id(charId);
	rsp.set_box_id(boxId);
	rsp.set_max_lev_box(maxLevBoxFlag);
	if (!g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_UNION, CENTER_TO_LOGIC_UNION_FETCH_SCORE, &rsp))
	{
		LogErrFmtPrint("[center] UnionMgr::NotifyLogicFetchScore...SendDataToLogicByCharID failed....charid:%lu,boxid:%u ", charId, boxId);
	}
}

//通知逻辑服绑定工会驻地成功
void UnionMgr::NotifyLogicBindHome(uint32_t unionId, uint32_t sceneId,uint32_t logicId)
{
	CL_UnionCreateHomeRsp rsp;
	rsp.set_union_id(unionId);
	rsp.set_scene_id(sceneId);
	if (!g_GetCenterService()->SendDataToLogic(logicId, EMODULE_ID_UNION, CENTER_TO_LOGIC_UNION_HOME_SCENE_BIND, &rsp))
	{
		LogErrFmtPrint("[center] UnionMgr::NotifyLogicCreateHome...SendDataToLogic failed....logicId:%u, unionid:%u, sceneid:%u ",logicId,unionId,sceneId);
	}
}

//通知逻辑服工会解散
void UnionMgr::NotifyLogicDismiss(uint32_t unionId, uint32_t sceneId,uint32_t logicId)
{
	CL_UnionDismissRsp rsp;
	rsp.set_union_id(unionId);
	rsp.set_scene_id(sceneId);
	if (!g_GetCenterService()->SendDataToLogic(logicId, EMODULE_ID_UNION, CENTER_TO_LOGIC_UNION_DISMISS, &rsp))
	{
		LogErrFmtPrint("[center] UnionMgr::NotifyLogicDismiss...SendDataToLogic failed....unionID:%u, sceneid:%u, logicID:%u ",unionId,sceneId,logicId );
	}
}

//通知逻辑服工会等级更新
void UnionMgr::NotifyLogicUnionLevUpdate(uint32_t unionId, int32_t level, uint32_t sceneId)
{
	uint32_t logicId = g_GetCenterDuplicateMgr()->dupSceneLogic(sceneId);
	if (logicId > 0)
	{
		CL_UnionLevUpdateRsp rsp;
		rsp.set_union_id(unionId);
		rsp.set_scene_id(sceneId);
		rsp.set_union_lev(level);
		g_GetCenterService()->SendDataToLogic(logicId, EMODULE_ID_UNION, CENTER_TO_LOGIC_UNION_LEVEL_UPDATE, &rsp);
	}
}

//通知工会有申请列表有变动
void UnionMgr::NotifyApplyLstUpdate(uint32_t unionId, CharIDType charId /*= 0*/)
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr != pUnion)
	{
		UnionApplyLstNotify notify;
		if (charId > 0)
		{
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_UNION, CENTER_TO_CLIENT_UNION_APPLY_LST_NOTIFY, &notify);
		}
		else
		{
			SET_INT8 setDuty = g_GetUnionCfgMgr()->GetApplyLstDuty();			
			pUnion->BroadUnionData(EMODULE_ID_UNION, CENTER_TO_CLIENT_UNION_APPLY_LST_NOTIFY, &notify, setDuty);
		}
	}
}

//通知工会驻地首领外观改变
void UnionMgr::NotifyLeaderFacadeUpdate(uint32_t unionId)
{
	CUnion *pUnion = GetUnion(unionId);
	if (nullptr != pUnion)
	{
		uint32_t sceneId = pUnion->UnionSceneId();
		uint32_t logicId = g_GetCenterDuplicateMgr()->dupSceneLogic(sceneId);
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pUnion->LeaderId());
		if (nullptr != pOffline)
		{
			CL_UnionLeaderFacadeNotify notify;
			notify.set_scene_id(sceneId);
			CharOutward *outWard = notify.mutable_facade();
			outWard->set_prof(pOffline->GetProf());
			outWard->set_sex(pOffline->GetSex());
			outWard->set_dstname(pOffline->GetCharName());
			CharFacadeProto *proto = outWard->mutable_facade();
			proto->CopyFrom(pOffline->GetFacade());
			g_GetCenterService()->SendDataToLogic(logicId, EMODULE_ID_UNION, CENTER_TO_LOGIC_UNION_LEADER_FACADE_NOTIFY, &notify);
		}
		else
		{
			LogErrFmtPrint("[center] UnionMgr::NotifyLeaderFacadeUpdate..... nullptr == pOffline  unionid:%u, leaderid:%lu ", unionId, pUnion->LeaderId());
		}
	}
}


//创建工会广播
void UnionMgr::BroadCastCreateUnion(uint32_t unionId, const char *szUnionName, CharIDType charId)
{
	SystemChatMsgData notify;	
	CharacterPlayerMiniInfo playerInfo;
	g_GetChatCenter()->InitPlayerMiniInfoStruct(charId, playerInfo);
	notify.players.push_back(playerInfo);
	notify.text.push_back(szUnionName);
	notify.params.push_back(unionId);
	g_GetChatCenter()->SendWorldBroadcastChat(BT_UNION_CREATE_UNION_SUCESS, notify);
}

//加入和离开工会的广播 type : 0 离开，1 加入
void UnionMgr::BroadCastJoinAndQuit(SET_UINT64 &setMember, CharIDType charId, int8_t type)
{
	SystemChatMsgData notify;
	CharacterPlayerMiniInfo playerInfo;
	g_GetChatCenter()->InitPlayerMiniInfoStruct(charId, playerInfo);
	notify.players.push_back(playerInfo);
	BROADCAST_TYPE bt = BT_UNION_QUIT_UNION;
	if (type)
	{
		bt = BT_UNION_JOIN_UNION;
	}	
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);
}

//被踢出工会的广播
void UnionMgr::BroadCastKickOut(SET_UINT64 &setMember, int8_t duty, const char *szName, const char *szKickName)
{
	SystemChatMsgData notify;
	notify.text.push_back(szKickName);
	notify.text.push_back(szName);
	notify.params.push_back(duty);
	g_GetChatCenter()->SendBroadcastChat(BT_UNION_BE_KICK_OUT, notify, setMember);
}

//会长转让广播
void UnionMgr::BroadCastLeaderTrans(SET_UINT64 &setMember, const char* szName)
{
	SystemChatMsgData notify;
	notify.text.push_back(szName);
	g_GetChatCenter()->SendBroadcastChat(BT_UNION_LEADER_TRANSFER, notify, setMember);
}

//政变广播 type:0 发起，1 成功，2 失败
void UnionMgr::BroadCastCoup(SET_UINT64 &setMember, const char* szName, int8_t type)
{
	SystemChatMsgData notify;
	notify.text.push_back(szName);
	BROADCAST_TYPE bt = BT_UNION_FAILED_COUP;
	if (0 == type)
	{
		bt = BT_UNION_START_COUP;
	}
	else if (1 == type)
	{
		bt = BT_UNION_SUCESS_COUP;
	}
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);	
}

//建筑升级广播
void UnionMgr::BroadCastBuildUpgrade(SET_UINT64 &setMember, int8_t buildType, int8_t level)
{
	SystemChatMsgData notify;
	notify.params.push_back(buildType);
	notify.params.push_back(level);
	g_GetChatCenter()->SendBroadcastChat(BT_UNION_BUILD_UPGRADE, notify, setMember);
}

//扣除维护费用广播
void UnionMgr::BroadCastCostCharge(SET_UINT64 &setMember, int32_t costMoney)
{
	SystemChatMsgData notify;
	notify.params.push_back(costMoney);
	g_GetChatCenter()->SendBroadcastChat(BT_UNION_COST_CHARGE, notify, setMember);
}

//扣除研究费用广播
void UnionMgr::BroadCastCostResearch(SET_UINT64 &setMember, int8_t type, int32_t level,int32_t costMoney)
{
	SystemChatMsgData notify;
	notify.params.push_back(level);
	notify.params.push_back(type);
	notify.params.push_back(costMoney);
	g_GetChatCenter()->SendBroadcastChat(BT_UNION_COST_RESEARCH, notify, setMember);
}
//进入警戒线广播 type: 1 警戒，0 非警戒
void UnionMgr::BroadCastWarnLine(SET_UINT64 &setMember, int32_t warnLine, int8_t type)
{
	SystemChatMsgData notify;
	notify.params.push_back(warnLine);
	BROADCAST_TYPE bt = BT_UNION_LEAVE_WARN_LINE;
	if (type)
	{
		bt = BT_UNION_ENTER_WARN_LINE;
	}
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);
}
//工会功能限制广播 type: 1 限制，0 非限制
void UnionMgr::BroadCastFuncLimit(SET_UINT64 &setMember, int8_t type)
{
	SystemChatMsgData notify;
	BROADCAST_TYPE bt = BT_UNION_REMOVE_LIMIT_STATE;
	if (type)
	{
		bt = BT_UNION_ENTER_LIMIT_STATE;
	}
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);
}

//编辑公告广播
void UnionMgr::BroadCastEditNotice(CharIDType charId, string &strNotice)
{
	ProtoBuf::GCChatMsgRsp chatMsgRsp;
	chatMsgRsp.set_chattype(CHAT_TYPE_GUILD);
	CharacterPlayerMiniInfo *protoInfo = chatMsgRsp.mutable_fromplayerinfo();
	g_GetChatCenter()->InitPlayerMiniInfoStruct(charId,*protoInfo);
	ChatContentInfo *proto = chatMsgRsp.add_chatcontent();
	if (nullptr != proto)
	{
		proto->set_describes(strNotice);
	}
	g_GetChatCenter()->SendUnionMsg(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, charId, &chatMsgRsp);
}

//哥布林出现
void UnionMgr::BroadCastGoblinAppear(SET_UINT64 &setMember)
{
	SystemChatMsgData notify;
	BROADCAST_TYPE bt = BT_UNION_GOBLIN_NPC_ROB;
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);
}
//远古精灵出现
void UnionMgr::BroadCastAncientElfApprear(SET_UINT64 &setMember)
{
	SystemChatMsgData notify;
	BROADCAST_TYPE bt = BT_UNION_ANCIENT_ELF_APPEAR;
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);
}

//云端试炼开启
void UnionMgr::BroadCastCloudOpen(SET_UINT64 &setMember)
{
	SystemChatMsgData notify;
	BROADCAST_TYPE bt = BT_UNION_CLOUD_OPEN;
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);
}

//哥布林偷取工会资金
void UnionMgr::BroadCastStealMoney(SET_UINT64 &setMember, int32_t money)
{
	SystemChatMsgData notify;
	notify.params.push_back(money);
	BROADCAST_TYPE bt = BT_UNION_GOBLIN_STEAL_MONEY;
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);
}

//击杀所有的哥布林怪
void UnionMgr::BroadCastKillAllGoblin(SET_UINT64 &setMember)
{
	SystemChatMsgData notify;
	BROADCAST_TYPE bt = BT_UNION_GOBLIN_KILL_ALL_MONS;
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);
}
//击杀哥布林头子
void UnionMgr::BroadCastKillGoblinBoss(SET_UINT64 &setMember)
{
	SystemChatMsgData notify;
	BROADCAST_TYPE bt = BT_UNION_GOBLIN_KILL_BOSS;
	g_GetChatCenter()->SendBroadcastChat(bt, notify, setMember);
}

//通知逻辑服 工会活动状态
void UnionMgr::NotifyLogicActState(uint32_t unionId, uint32_t actSceneId, uint32_t logicId, uint32_t activityId, int32_t state,int32_t averageLev/* = 0*/)
{
	CL_UnionActivityStateRsp rsp;
	rsp.set_union_id(unionId);
	rsp.set_scene_id(actSceneId);
	rsp.set_activity_id(activityId);
	rsp.set_state(state);
	rsp.set_average_level(averageLev);
	g_GetCenterService()->SendDataToLogic(logicId, EMODULE_ID_UNION, CENTER_TO_LOGIC_UNION_ACTIVITY_STATE, &rsp);
}
void UnionMgr::NotifyLogicActState(uint32_t logicId,uint32_t actId,int32_t state,SUnionActParam &param)
{
	CL_UnionActivityStateRsp rsp;
	rsp.set_union_id(param.unionId);
	rsp.set_scene_id(param.actScene);
	rsp.set_activity_id(actId);
	rsp.set_state(state);
	rsp.set_average_level(param.averageLev);
	rsp.set_vault_level(param.vaultLev);
	rsp.set_college_level(param.collegeLev);
	g_GetCenterService()->SendDataToLogic(logicId, EMODULE_ID_UNION, CENTER_TO_LOGIC_UNION_ACTIVITY_STATE, &rsp);
}

//通知逻辑服 工会地宫关闭
void UnionMgr::NotifyLogicDungeonClose(uint32_t unionId, uint32_t dungeonSceneId, uint32_t dungeonLogicId)
{
	CL_UnionDungeonCloseRsp rsp;
	rsp.set_union_id(unionId);
	rsp.set_scene_id(dungeonSceneId);
	g_GetCenterService()->SendDataToLogic(dungeonLogicId, EMODULE_ID_UNION, CENTER_TO_LOGIC_UNION_DUNGEON_CLOSE, &rsp);
}

void UnionMgr::UpdateCloudScore(uint32_t unionId, uint64_t totalScore, MAP_UINT64_INT32 &mapCharScore) 	//更新云端试炼积分
{
	if (totalScore > 0)
	{
		UnionCloudScoreRank(unionId, totalScore);
	}
	
	
	MAP_UINT64_INT32::iterator iterChar = mapCharScore.begin();
	for (; iterChar != mapCharScore.end(); ++iterChar)
	{
		if (iterChar->second > 0)
		{
			CharCloudScoreRank(iterChar->first, iterChar->second);
		}		
	}
}

void UnionMgr::ClearScoreRank()	//清空积分排名
{
	m_vecUnionRank.clear();
	m_vecCharRank.clear();

}
bool UnionMgr::ScoreCompareFunc(const SUnionScoreRank &elemA, const SUnionScoreRank &elemB) //排名比较函数
{
	return elemA.rankScore > elemB.rankScore;
}

void UnionMgr::UnionCloudScoreRank(uint32_t unionId, uint64_t totalScore)	//工会积分排名
{
	bool brank = false;
	bool bFind = false;
	//先查询下，工会是否已经再排名中
	int32_t unionRankSize = m_vecUnionRank.size();
	for (int32_t i = 0; i < unionRankSize; ++i)
	{
		SUnionScoreRank &elem = m_vecUnionRank.at(i);
		if (unionId == elem.rankId)
		{
			bFind = true;
			if (elem.rankScore != totalScore) //积分有变化才需要重新排序
			{
				elem.rankScore = totalScore;
				brank = true;				
				break;
			}
		}
	}

	if (!bFind) //如果不在排名中
	{
		if (unionRankSize >= UNION_UNION_SCORE_COUNT)
		{
			//积分排名从大到小，如果排名列表已满，取最后一个比较即可
			SUnionScoreRank &lastElem = m_vecUnionRank.at(unionRankSize - 1);
			if (lastElem.rankScore < totalScore)
			{
				lastElem.rankId = unionId;
				lastElem.rankScore = totalScore;
				brank = true;
			}
		}
		else
		{
			SUnionScoreRank rank;
			rank.rankId = unionId;
			rank.rankScore = totalScore;
			m_vecUnionRank.push_back(rank);
			brank = true;
		}
	}

	if (brank)
	{
		std::sort(m_vecUnionRank.begin(), m_vecUnionRank.end(), ScoreCompareFunc);
	}
}

void UnionMgr::CharCloudScoreRank(CharIDType charId, int32_t score)	//玩家积分排名
{
	bool brank = false;
	bool bFind = false;
	//先查询下，工会是否已经再排名中
	int32_t isize = m_vecCharRank.size();
	for (int32_t i = 0; i < isize; ++i)
	{
		SUnionScoreRank &elem = m_vecCharRank.at(i);
		if (charId == elem.rankId)
		{
			bFind = true;
			if (elem.rankScore != (uint64_t)score) //积分有变化才需要重新排序
			{
				elem.rankScore = (uint64_t)score;
				brank = true;				
				break;
			}
		}
	}

	if (!bFind) //如果不在排名中
	{
		if (isize >= UNION_PERSONAL_SCORE_COUNT)
		{
			//积分排名从大到小，如果排名列表已满，取最后一个比较即可
			SUnionScoreRank &lastElem = m_vecCharRank.at(isize - 1);
			if (lastElem.rankScore < (uint64_t)score)
			{
				lastElem.rankId = charId;
				lastElem.rankScore = (uint64_t)score;
				brank = true;
			}
		}
		else
		{
			SUnionScoreRank rank;
			rank.rankId = charId;
			rank.rankScore = (uint64_t)score;
			m_vecCharRank.push_back(rank);
			brank = true;
		}
	}
	
	if (brank)
	{
		std::sort(m_vecCharRank.begin(), m_vecCharRank.end(), ScoreCompareFunc);
	}
}

void UnionMgr::CloudScoreQuit(CharIDType charId)		//玩家退出工会积分排名处理
{
	DelCharCloudScore(charId);
}

void UnionMgr::CloudScoreDismiss(uint32_t unionId)	//工会解散积分排名处理
{
	DelUnionCloudScore(unionId);
}

void UnionMgr::DelUnionCloudScore(uint32_t unionId)	//删除工会积分
{
	VecScoreRank::iterator iter = m_vecUnionRank.begin();
	for (; iter != m_vecUnionRank.end(); ++iter)
	{
		if (iter->rankId == unionId)
		{
			m_vecUnionRank.erase(iter);
			break;
		}
	}
}

void UnionMgr::DelCharCloudScore(CharIDType charId)	//删除玩家积分
{
	VecScoreRank::iterator iter = m_vecCharRank.begin();
	for (; iter != m_vecCharRank.end(); ++iter)
	{
		if (iter->rankId == charId)
		{
			m_vecCharRank.erase(iter);
			break;
		}
	}
}

void UnionMgr::OnFinishLoadAllUnionDBData()	//加载完所有工会DB数据
{
	//需要检查每个工会的云端试炼副本 通关和积分数据
	/*
	1、如果当前在活动时间内，并且上次已经通关了云端试炼活动的工会，
	  需要比较下两次时间是否在一次活动时间内，如果在一次活动时间内，就不需要清空通关和积分数据，
	  否则就需要清空了
	2、需要对上一次的活动积分数据进行一次排名
	*/

	uint32_t cloudActId = g_GetDuplicateCfgMgr()->GetCloudActId();
	CActivity *pCloudAct = g_GetActivityMgr()->GetActivity(cloudActId);
	if (nullptr != pCloudAct)
	{
		if (pCloudAct->IsRuning())
		{
			uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
			uint64_t startTime = pCloudAct->GetStartTime();
			uint64_t endTime = curTime + pCloudAct->GetLeftTime();
			UnionMap::iterator iter = m_mapUnion.begin();
			for (; iter != m_mapUnion.end(); ++iter)
			{
				CUnion *pUnion = iter->second;
				if (nullptr != pUnion)
				{
					uint64_t lastUpdate = pUnion->LastCloudUpdate();
					if (lastUpdate <= startTime || lastUpdate >= endTime)
					{
						//上次通关时间不在在此次活动时间内的,直接清空数据
						pUnion->ClearCloudScore();
						//
					}
				}
			}
		}
		//需要重新对积分排名			
		MAP_UINT64_INT32 mapCharScore;
		UnionMap::iterator iter = m_mapUnion.begin();
		for (; iter != m_mapUnion.end(); ++iter)
		{
			CUnion *pUnion = iter->second;
			if (nullptr != pUnion)
			{
				mapCharScore.clear();
				pUnion->MemCloudScore(mapCharScore);
				UpdateCloudScore(pUnion->UnionId(), pUnion->TotalScore(), mapCharScore);
			}
		}
	}
}

uint32_t UnionMgr::GetCloudScoreBoxId(int32_t score) //根据积分获取奖励宝箱ID
{
	/*LuaScript *pScript = g_GetCSScriptMgr()->GetScript();
	if (nullptr == pScript)
	{
		LogErrFmtPrint("[center] UnionMgr::GetCloudScoreBoxId....nullptr == pScript...");
		return 0;
	}
	LuaRef ref(pScript->GetState());
	if (!pScript->CallTableFuncRet("Activity", "LuaCloudBoxId", ref))
	{
		LogErrFmtPrint("[center] UnionMgr::GetCloudScoreBoxId...pScript->CallTableFuncRet failed...");
		return 0;
	}
	return ref.cast<uint32_t>();*/

	const GuildDungeonboxCfgInfo *pScoreLevCfg = g_GetUnionCfgMgr()->GetScoreLevCfgByScore(score);
	if (nullptr != pScoreLevCfg)
	{
		return pScoreLevCfg->box_id;
	}
	return 0;
}

void UnionMgr::LogCurrencyContri(OfflineCharacterData *pOffline, int32_t contri, ItemOrCurrencySource source)
{
	uint32_t tid = 0;
	if (contri > 0)
		tid = TID_CURRENCY_GET;
	else
	{
		tid = TID_CURRENCY_DEL;
		contri = -contri;
	}

	rapidjson::Document doc;
	JsonObject obj(&doc);

	if (source > S_END)
	{
		LogErrFmtPrint("source Id not have name, id:%d", source);
		obj.AddString("sourceName", "none");
	}
	else
		obj.AddString("souceName", l_source_name[source]);


	obj.AddUInt32("tid", tid);
	obj.AddUInt32("chanid",pOffline->GetChannelId());
	obj.AddUInt32("uid", pOffline->GetUid());
	obj.AddUInt64("rid", pOffline->GetCharID());
	obj.AddUInt64("time", g_GetGlobalServerTime()->UnixSec());
	obj.AddUInt32("rjob", pOffline->GetProf());
	obj.AddUInt32("rsex", pOffline->GetSex());
	obj.AddInt32("camp",  pOffline->GetCampID());
	obj.AddUInt32("level", pOffline->GetLevel());
	obj.AddUInt32("race",  pOffline->GetRace());
	obj.AddUInt32("zid", g_GetCenterService()->GetZoneId());

	obj.AddString("currencyName", "工会贡献");
	obj.AddUInt32("currencyId", C_UNION_CONTRI);
	obj.AddUInt32("source", source);
	obj.AddUInt32("num", contri);

	if (!g_GetCenterService()->SendLogToLogServer(obj))
		LogErrPrint("UnionMgr::LogCurrencyContri, SendLogToLogServer, contri");

}